[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



On 2015-09-04 11:25, Paul Durrant wrote:
>> -----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_.
> 
Alright. I thought I saw them in there but maybe that was in Linux libxc 
implementation.

>> +
>> +/*! \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().

That makes sense, when I was writing this I just deferred to how other store 
calls work.
> 
>   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


-- 
RafaÅ WojdyÅa
Qubes Tools for Windows developer
https://www.qubes-os.org/

_______________________________________________
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®.