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