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

Re: [win-pv-devel] [PATCH 2/2] Add support for changing key permissions to the STORE interface



> -----Original Message-----
> From: win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx [mailto:win-pv-devel-
> bounces@xxxxxxxxxxxxxxxxxxxx] On Behalf Of Rafal Wojdyla
> Sent: 25 August 2015 17:16
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Subject: [win-pv-devel] [PATCH 2/2] Add support for changing key
> permissions to the STORE interface
> 
> STORE interface now includes a function to change key permissions. This
> allows granting key access to other, non-privileged domains.
> 
> Signed-off-by: RafaÅ WojdyÅa <omeg@xxxxxxxxxxxxxxxxxxxxxx>
> ---
>  include/store_interface.h |  68 ++++++++++++-
>  src/xenbus/store.c        | 254
> +++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 317 insertions(+), 5 deletions(-)
> 
> diff --git a/include/store_interface.h b/include/store_interface.h
> index 5bcbba3..a34b816 100644
> --- a/include/store_interface.h
> +++ b/include/store_interface.h
> @@ -50,6 +50,23 @@ typedef struct _XENBUS_STORE_TRANSACTION
> XENBUS_STORE_TRANSACTION, *PXENBUS_S
>  */
>  typedef struct _XENBUS_STORE_WATCH          XENBUS_STORE_WATCH,
> *PXENBUS_STORE_WATCH;
> 
> +/*! \typedef XENBUS_STORE_PERMISSION_MASK
> +    \brief Bitmask of XenStore key permissions
> + */
> +typedef enum _XENBUS_STORE_PERMISSION_MASK {
> +    XS_PERM_NONE = 0,
> +    XS_PERM_READ = 1,
> +    XS_PERM_WRITE = 2,
> +} XENBUS_STORE_PERMISSION_MASK;

These values are not defined in xs_wire.h so I think they need a XENBUS_STORE_ 
prefix rather than XS_.

> +
> +/*! \typedef XENBUS_STORE_PERMISSION
> +    \brief XenStore key permissions entry for a single domain
> + */
> +typedef struct _XENBUS_STORE_PERMISSION {
> +    USHORT Domain;
> +    XENBUS_STORE_PERMISSION_MASK Mask;
> +} XENBUS_STORE_PERMISSION, *PXENBUS_STORE_PERMISSION;
> +
>  /*! \typedef XENBUS_STORE_ACQUIRE
>      \brief Acquire a reference to the STORE interface
> 
> @@ -247,10 +264,36 @@ typedef VOID
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENBUS_STORE_PERMISSIONS_SET
> +    \brief Set permissions for a XenStore key
> +
> +    \param Interface The interface header
> +    \param Transaction The transaction handle (NULL if this is not
> +    part of a transaction)
> +    \param Prefix An optional prefix for the \a Node
> +    \param Node The concatenation of the \a Prefix and this value specifies
> +    the XenStore key to set permissions of
> +    \param Permissions An array of permissions to set
> +    \param NumberPermissions Number of elements in the \a Permissions
> array
> + */
> +typedef NTSTATUS
> +(*XENBUS_STORE_PERMISSIONS_SET)(
> +    IN  PINTERFACE                  Interface,
> +    IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,
> +    IN  PCHAR                       Prefix OPTIONAL,
> +    IN  PCHAR                       Node,
> +    IN  PXENBUS_STORE_PERMISSION    Permissions,
> +    IN  ULONG                       NumberPermissions
> +    );
> +
>  // {86824C3B-D34E-4753-B281-2F1E3AD214D7}
>  DEFINE_GUID(GUID_XENBUS_STORE_INTERFACE,
>  0x86824c3b, 0xd34e, 0x4753, 0xb2, 0x81, 0x2f, 0x1e, 0x3a, 0xd2, 0x14, 0xd7);
> 
> +/*! \struct _XENBUS_STORE_INTERFACE_V1
> +    \brief STORE interface version 1
> +    \ingroup interfaces
> + */
>  struct _XENBUS_STORE_INTERFACE_V1 {
>      INTERFACE                       Interface;
>      XENBUS_STORE_ACQUIRE            StoreAcquire;
> @@ -267,11 +310,28 @@ struct _XENBUS_STORE_INTERFACE_V1 {
>      XENBUS_STORE_POLL               StorePoll;
>  };
> 
> -/*! \struct _XENBUS_STORE_INTERFACE_V1
> -    \brief STORE interface version 1
> +/*! \struct _XENBUS_STORE_INTERFACE_V2
> +    \brief STORE interface version 2
>      \ingroup interfaces
>  */
> -typedef struct _XENBUS_STORE_INTERFACE_V1
> XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
> +struct _XENBUS_STORE_INTERFACE_V2 {
> +    INTERFACE                       Interface;
> +    XENBUS_STORE_ACQUIRE            StoreAcquire;
> +    XENBUS_STORE_RELEASE            StoreRelease;
> +    XENBUS_STORE_FREE               StoreFree;
> +    XENBUS_STORE_READ               StoreRead;
> +    XENBUS_STORE_PRINTF             StorePrintf;
> +    XENBUS_STORE_REMOVE             StoreRemove;
> +    XENBUS_STORE_DIRECTORY          StoreDirectory;
> +    XENBUS_STORE_TRANSACTION_START  StoreTransactionStart;
> +    XENBUS_STORE_TRANSACTION_END    StoreTransactionEnd;
> +    XENBUS_STORE_WATCH_ADD          StoreWatchAdd;
> +    XENBUS_STORE_WATCH_REMOVE       StoreWatchRemove;
> +    XENBUS_STORE_POLL               StorePoll;
> +    XENBUS_STORE_PERMISSIONS_SET    StorePermissionsSet;
> +};
> +
> +typedef struct _XENBUS_STORE_INTERFACE_V2
> XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
> 
>  /*! \def XENBUS_STORE
>      \brief Macro at assist in method invocation
> @@ -282,7 +342,7 @@ typedef struct _XENBUS_STORE_INTERFACE_V1
> XENBUS_STORE_INTERFACE, *PXENBUS_STORE
>  #endif  // _WINDLL
> 
>  #define XENBUS_STORE_INTERFACE_VERSION_MIN  1
> -#define XENBUS_STORE_INTERFACE_VERSION_MAX  1
> +#define XENBUS_STORE_INTERFACE_VERSION_MAX  2
> 
>  #endif  // _XENBUS_STORE_INTERFACE_H
> 
> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
> index 16ca37b..2642bb3 100644
> --- a/src/xenbus/store.c
> +++ b/src/xenbus/store.c
> @@ -236,6 +236,73 @@ fail1:
>      return status;
>  }
> 
> +// prepare a request with known number of elements
> +static NTSTATUS
> +StorePrepareRequestFixed(
> +    IN  PXENBUS_STORE_CONTEXT       Context,
> +    OUT PXENBUS_STORE_REQUEST       Request,
> +    IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,
> +    IN  enum xsd_sockmsg_type       Type,
> +    IN  PXENBUS_STORE_SEGMENT       Segments,
> +    IN  ULONG                       NumberSegments
> +    )
> +{
> +    ULONG                           Id;
> +    KIRQL                           Irql;
> +    NTSTATUS                        status;
> +    ULONG                           Index;
> +
> +    ASSERT(IsZeroMemory(Request, sizeof (XENBUS_STORE_REQUEST)));
> +
> +    status = STATUS_INVALID_PARAMETER;
> +    if (NumberSegments > XENBUS_STORE_REQUEST_SEGMENT_COUNT - 1)
> // need one for the header
> +        goto fail1;
> +
> +    if (Transaction != NULL) {
> +        status = STATUS_UNSUCCESSFUL;
> +        if (!Transaction->Active)
> +            goto fail2;
> +
> +        Id = Transaction->Id;
> +    } else {
> +        Id = 0;
> +    }
> +
> +    Request->Header.type = Type;
> +    Request->Header.tx_id = Id;
> +    Request->Header.len = 0;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +    Request->Header.req_id = Context->RequestId++;
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    // header is the first, then the actual data
> +    Request->Count = NumberSegments + 1;
> +
> +    Request->Segment[0].Data = (PCHAR)&Request->Header;
> +    Request->Segment[0].Offset = 0;
> +    Request->Segment[0].Length = sizeof(struct xsd_sockmsg);
> +

I don't think you need this new function. See below...

> +    for (Index = 0; Index < NumberSegments; Index++) {
> +        Request->Segment[Index+1].Data = Segments[Index].Data;
> +        Request->Segment[Index+1].Offset = 0;
> +        Request->Segment[Index+1].Length = Segments[Index].Length;
> +
> +        Request->Header.len += Segments[Index].Length;
> +    }
> +
> +    Request->State = XENBUS_STORE_REQUEST_PREPARED;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> +
>  static ULONG
>  StoreCopyToRing(
>      IN  PXENBUS_STORE_CONTEXT           Context,
> @@ -439,7 +506,6 @@ StoreIgnoreHeaderType(
>      case XS_RELEASE:
>      case XS_GET_DOMAIN_PATH:
>      case XS_MKDIR:
> -    case XS_SET_PERMS:
>      case XS_IS_DOMAIN_INTRODUCED:
>      case XS_RESUME:
>      case XS_SET_TARGET:
> @@ -467,6 +533,7 @@ StoreVerifyHeader(
>          Header->type != XS_TRANSACTION_END &&
>          Header->type != XS_WRITE &&
>          Header->type != XS_RM &&
> +        Header->type != XS_SET_PERMS &&
>          Header->type != XS_WATCH_EVENT &&
>          Header->type != XS_ERROR &&
>          !StoreIgnoreHeaderType(Header->type)) {
> @@ -1788,6 +1855,157 @@ StorePoll(
>      KeReleaseSpinLockFromDpcLevel(&Context->Lock);
>  }
> 
> +static NTSTATUS
> +StorePermissionToString(
> +    IN  PXENBUS_STORE_PERMISSION Permission,
> +    IN  ULONG BufferSize,
> +    OUT PCHAR Buffer
> +    )
> +{
> +    NTSTATUS status = STATUS_INVALID_PARAMETER;
> +
> +    ASSERT(BufferSize > 1);
> +
> +    switch (Permission->Mask) {
> +    case XS_PERM_WRITE:
> +        *Buffer = 'w';
> +        break;
> +    case XS_PERM_READ:
> +        *Buffer = 'r';
> +        break;
> +    case XS_PERM_READ | XS_PERM_WRITE:
> +        *Buffer = 'b';
> +        break;
> +    case XS_PERM_NONE:
> +        *Buffer = 'n';
> +        break;
> +    default:
> +        goto fail1;
> +    }
> +
> +    return RtlStringCbPrintfA(Buffer + 1, BufferSize - 1, "%u", Permission-
> >Domain);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> +
> +static NTSTATUS
> +StorePermissionsSet(
> +    IN  PINTERFACE                  Interface,
> +    IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,
> +    IN  PCHAR                       Prefix OPTIONAL,
> +    IN  PCHAR                       Node,
> +    IN  PXENBUS_STORE_PERMISSION    Permissions,
> +    IN  ULONG                       NumberPermissions
> +    )
> +{
> +    PXENBUS_STORE_CONTEXT           Context = Interface->Context;
> +    XENBUS_STORE_REQUEST            Request;
> +    PXENBUS_STORE_RESPONSE          Response;
> +    NTSTATUS                        status;
> +    XENBUS_STORE_SEGMENT
> Segments[XENBUS_STORE_REQUEST_SEGMENT_COUNT];
> +    ULONG                           Index, BufferSize;
> +    PCHAR                           Path = NULL;
> +
> +    status = STATUS_INVALID_PARAMETER;
> +    if (NumberPermissions > XENBUS_STORE_REQUEST_SEGMENT_COUNT -
> 2) // 1 for path, 1 for header in StorePrepareRequestFixed
> +        goto fail1;
> +
> +    if (Prefix != NULL) {
> +        // we're concatenating it here instead of passing to
> StorePrepareRequestFixed to reduce the number of segments used
> +        status = STATUS_NO_MEMORY;
> +        Path = __StoreAllocate(XENSTORE_ABS_PATH_MAX);
> +        if (Path == NULL)
> +            goto fail2;
> +
> +        status = RtlStringCbPrintfA(Path, XENSTORE_ABS_PATH_MAX,
> "%s/%s", Prefix, Node);
> +        ASSERT(NT_SUCCESS(status));
> +        Node = Path;
> +    }
> +
> +    RtlZeroMemory(&Request, sizeof(XENBUS_STORE_REQUEST));
> +    RtlZeroMemory(Segments, sizeof(Segments));
> +
> +    Segments[0].Data = Node; // path
> +    Segments[0].Offset = 0;
> +    Segments[0].Length = (ULONG)strlen(Node) + 1; // zero terminator
> required
> +
> +    BufferSize = 16;
> +    for (Index = 0; Index < NumberPermissions; Index++) {
> +        Segments[Index + 1].Data = __StoreAllocate(BufferSize);
> +        if (Segments[Index + 1].Data == NULL)
> +            goto fail3;
> +
> +        status = StorePermissionToString(&Permissions[Index], BufferSize,
> Segments[Index+1].Data);
> +        if (!NT_SUCCESS(status))
> +            goto fail4;
> +
> +        Segments[Index + 1].Length = (ULONG)strlen(Segments[Index +
> 1].Data) + 1; // zero terminator required
> +    }
> +
> +    status = StorePrepareRequestFixed(Context,
> +                                      &Request,
> +                                      Transaction,
> +                                      XS_SET_PERMS,
> +                                      Segments,
> +                                      NumberPermissions + 1);
> +

Segments are only a coding convenience... On the 'wire' they are just 
concatenated. So I think all you need to is prepare character buffer with a NUL 
separated list of <perm><domid> strings and then pass that as an arg to the 
normal ellipsis StorePrepareRequest(). No need for the extra complexity of a 
new StorePrepareRequestFixed().

  Paul

> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> +
> +    Response = StoreSubmitRequest(Context, &Request);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Response == NULL)
> +        goto fail6;
> +
> +    status = StoreCheckResponse(Response);
> +    if (!NT_SUCCESS(status))
> +        goto fail7;
> +
> +    StoreFreeResponse(Response);
> +    ASSERT(IsZeroMemory(&Request, sizeof(XENBUS_STORE_REQUEST)));
> +    for (Index = 0; Index < NumberPermissions; Index++)
> +        __StoreFree(Segments[Index + 1].Data);
> +
> +    if (Path != NULL)
> +        __StoreFree(Path);
> +
> +    return STATUS_SUCCESS;
> +
> +fail7:
> +    Error("fail7\n");
> +    StoreFreeResponse(Response);
> +
> +fail6:
> +    Error("fail6\n");
> +
> +fail5:
> +    Error("fail5\n");
> +
> +fail4:
> +    Error("fail4\n");
> +
> +fail3:
> +    Error("fail3\n");
> +    for (Index = 0; Index < NumberPermissions; Index++)
> +        if (Segments[Index + 1].Data != NULL)
> +            __StoreFree(Segments[Index + 1].Data);
> +
> +    if (Path != NULL)
> +        __StoreFree(Path);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    ASSERT(IsZeroMemory(&Request, sizeof(XENBUS_STORE_REQUEST)));
> +    return status;
> +}
> +
>  static
>  _Function_class_(KSERVICE_ROUTINE)
>  _IRQL_requires_(HIGH_LEVEL)
> @@ -2285,6 +2503,23 @@ static struct _XENBUS_STORE_INTERFACE_V1
> StoreInterfaceVersion1 = {
>      StorePoll
>  };
> 
> +static struct _XENBUS_STORE_INTERFACE_V2 StoreInterfaceVersion2 = {
> +    { sizeof(struct _XENBUS_STORE_INTERFACE_V2), 2, NULL, NULL, NULL },
> +    StoreAcquire,
> +    StoreRelease,
> +    StoreFree,
> +    StoreRead,
> +    StorePrintf,
> +    StoreRemove,
> +    StoreDirectory,
> +    StoreTransactionStart,
> +    StoreTransactionEnd,
> +    StoreWatchAdd,
> +    StoreWatchRemove,
> +    StorePoll,
> +    StorePermissionsSet,
> +};
> +
>  NTSTATUS
>  StoreInitialize(
>      IN  PXENBUS_FDO             Fdo,
> @@ -2384,6 +2619,23 @@ StoreGetInterface(
>          status = STATUS_SUCCESS;
>          break;
>      }
> +    case 2: {
> +        struct _XENBUS_STORE_INTERFACE_V2  *StoreInterface;
> +
> +        StoreInterface = (struct _XENBUS_STORE_INTERFACE_V2 *)Interface;
> +
> +        status = STATUS_BUFFER_OVERFLOW;
> +        if (Size < sizeof(struct _XENBUS_STORE_INTERFACE_V2))
> +            break;
> +
> +        *StoreInterface = StoreInterfaceVersion2;
> +
> +        ASSERT3U(Interface->Version, == , Version);
> +        Interface->Context = Context;
> +
> +        status = STATUS_SUCCESS;
> +        break;
> +    }
>      default:
>          status = STATUS_NOT_SUPPORTED;
>          break;
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

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