|
[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 |