[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [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; + +/*! \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); + + 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); + + 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |