]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Introduce VMCI firewall in device backend
authorVMware, Inc <>
Mon, 21 May 2012 22:19:20 +0000 (15:19 -0700)
committerDmitry Torokhov <dtor@vmware.com>
Tue, 22 May 2012 16:24:19 +0000 (09:24 -0700)
This change implements the VMCI device backend part of the
VMCI firewall.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/include/vmci_defs.h
open-vm-tools/modules/linux/shared/vmci_defs.h
open-vm-tools/modules/linux/vmci/common/vmciCommonInt.h
open-vm-tools/modules/linux/vmci/common/vmciContext.c
open-vm-tools/modules/linux/vmci/common/vmciContext.h
open-vm-tools/modules/linux/vmci/linux/vmci_version.h

index 3e0e753e858242927d0cdcae79011f5377f18267..6791b46cc3bcb3954770ad3c656def0ce1fac3cb 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2005-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2005-2012 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -143,10 +143,20 @@ typedef uint32 VMCI_Resource;
 #define VMCI_RPC_PRIVILEGED       15
 #define VMCI_RPC_UNPRIVILEGED     16
 #define VMCI_RESOURCE_MAX         17
+/*
+ * The core VMCI device functionality only requires the resource IDs of
+ * VMCI_QUEUEPAIR_DETACH and below.
+ */
+#define VMCI_CORE_DEVICE_RESOURCE_MAX  VMCI_QUEUEPAIR_DETACH
 
 /* VMCI Ids. */
 typedef uint32 VMCIId;
 
+typedef struct VMCIIdRange {
+   VMCIId begin;
+   VMCIId end;
+} VMCIIdRange;
+
 typedef struct VMCIHandle {
    VMCIId context;
    VMCIId resource;
@@ -827,5 +837,62 @@ VMCIQueueHeader_BufReady(const VMCIQueueHeader *consumeQHeader, // IN:
 }
 
 
-#endif
+/*
+ * Defines for the VMCI traffic filter:
+ * - VMCI_FP_<name> defines the filter protocol values
+ * - VMCI_FD_<name> defines the direction values (guest or host)
+ * - VMCI_FT_<name> are the type values (allow or deny)
+ */
+
+#define VMCI_FP_INVALID     -1
+#define VMCI_FP_HYPERVISOR   0
+#define VMCI_FP_QUEUEPAIR    (VMCI_FP_HYPERVISOR + 1)
+#define VMCI_FP_DOORBELL     (VMCI_FP_QUEUEPAIR + 1)
+#define VMCI_FP_DATAGRAM     (VMCI_FP_DOORBELL + 1)
+#define VMCI_FP_STREAMSOCK   (VMCI_FP_DATAGRAM + 1)
+#define VMCI_FP_SEQPACKET    (VMCI_FP_STREAMSOCK + 1)
+#define VMCI_FP_MAX          (VMCI_FP_SEQPACKET + 1)
+
+#define VMCI_FD_INVALID  -1
+#define VMCI_FD_GUEST     0
+#define VMCI_FD_HOST      (VMCI_FD_GUEST + 1)
+#define VMCI_FD_MAX       (VMCI_FD_HOST + 1)
+
+#define VMCI_FT_INVALID  -1
+#define VMCI_FT_ALLOW     0
+#define VMCI_FT_DENY      (VMCI_FT_ALLOW + 1)
+#define VMCI_FT_MAX       (VMCI_FT_DENY + 1)
+
+/*
+ * The filter list tracks VMCI Id ranges for a given filter.
+ */
+
+typedef struct {
+   uint32 len;
+   VMCIIdRange *list;
+} VMCIFilterList;
 
+
+/*
+ * The filter info is used to communicate the filter configuration
+ * from the VMX to the host kernel.
+ */
+
+typedef struct {
+   VA64   list;   // List of VMCIIdRange
+   uint32 len;    // Length of list
+   uint8  dir;    // VMCI_FD_X
+   uint8  proto;  // VMCI_FP_X
+   uint8  type;   // VMCI_FT_X
+} VMCIFilterInfo;
+
+/*
+ * In the host kernel, the ingoing and outgoing filters are
+ * separated. The VMCIProtoFilters type captures all filters in one
+ * direction. The VMCIFilters type captures all filters.
+ */
+
+typedef VMCIFilterList VMCIProtoFilters[VMCI_FP_MAX][VMCI_FT_MAX];
+typedef VMCIProtoFilters VMCIFilters[VMCI_FD_MAX];
+
+#endif
index b5483822d2173d7a835c4197b9bee154e7c54f4f..8222af7261d71fd8e930ef13a165cf2a1576ebb8 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2005-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2005-2012 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -143,10 +143,20 @@ typedef uint32 VMCI_Resource;
 #define VMCI_RPC_PRIVILEGED       15
 #define VMCI_RPC_UNPRIVILEGED     16
 #define VMCI_RESOURCE_MAX         17
+/*
+ * The core VMCI device functionality only requires the resource IDs of
+ * VMCI_QUEUEPAIR_DETACH and below.
+ */
+#define VMCI_CORE_DEVICE_RESOURCE_MAX  VMCI_QUEUEPAIR_DETACH
 
 /* VMCI Ids. */
 typedef uint32 VMCIId;
 
+typedef struct VMCIIdRange {
+   VMCIId begin;
+   VMCIId end;
+} VMCIIdRange;
+
 typedef struct VMCIHandle {
    VMCIId context;
    VMCIId resource;
@@ -827,5 +837,62 @@ VMCIQueueHeader_BufReady(const VMCIQueueHeader *consumeQHeader, // IN:
 }
 
 
-#endif
+/*
+ * Defines for the VMCI traffic filter:
+ * - VMCI_FP_<name> defines the filter protocol values
+ * - VMCI_FD_<name> defines the direction values (guest or host)
+ * - VMCI_FT_<name> are the type values (allow or deny)
+ */
+
+#define VMCI_FP_INVALID     -1
+#define VMCI_FP_HYPERVISOR   0
+#define VMCI_FP_QUEUEPAIR    (VMCI_FP_HYPERVISOR + 1)
+#define VMCI_FP_DOORBELL     (VMCI_FP_QUEUEPAIR + 1)
+#define VMCI_FP_DATAGRAM     (VMCI_FP_DOORBELL + 1)
+#define VMCI_FP_STREAMSOCK   (VMCI_FP_DATAGRAM + 1)
+#define VMCI_FP_SEQPACKET    (VMCI_FP_STREAMSOCK + 1)
+#define VMCI_FP_MAX          (VMCI_FP_SEQPACKET + 1)
+
+#define VMCI_FD_INVALID  -1
+#define VMCI_FD_GUEST     0
+#define VMCI_FD_HOST      (VMCI_FD_GUEST + 1)
+#define VMCI_FD_MAX       (VMCI_FD_HOST + 1)
+
+#define VMCI_FT_INVALID  -1
+#define VMCI_FT_ALLOW     0
+#define VMCI_FT_DENY      (VMCI_FT_ALLOW + 1)
+#define VMCI_FT_MAX       (VMCI_FT_DENY + 1)
+
+/*
+ * The filter list tracks VMCI Id ranges for a given filter.
+ */
+
+typedef struct {
+   uint32 len;
+   VMCIIdRange *list;
+} VMCIFilterList;
 
+
+/*
+ * The filter info is used to communicate the filter configuration
+ * from the VMX to the host kernel.
+ */
+
+typedef struct {
+   VA64   list;   // List of VMCIIdRange
+   uint32 len;    // Length of list
+   uint8  dir;    // VMCI_FD_X
+   uint8  proto;  // VMCI_FP_X
+   uint8  type;   // VMCI_FT_X
+} VMCIFilterInfo;
+
+/*
+ * In the host kernel, the ingoing and outgoing filters are
+ * separated. The VMCIProtoFilters type captures all filters in one
+ * direction. The VMCIFilters type captures all filters.
+ */
+
+typedef VMCIFilterList VMCIProtoFilters[VMCI_FP_MAX][VMCI_FT_MAX];
+typedef VMCIProtoFilters VMCIFilters[VMCI_FD_MAX];
+
+#endif
index 256b9dee5960bfad5ad5c003bc193e81262208fd..8af33b472c4bec1250499763cdc91d79abf8b47c 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2006-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2012 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -26,7 +26,6 @@
 #define _VMCI_COMMONINT_H_
 
 #define INCLUDE_ALLOW_MODULE
-#define INCLUDE_ALLOW_VMMON
 #define INCLUDE_ALLOW_VMCORE
 #define INCLUDE_ALLOW_VMKERNEL
 #include "includeCheck.h"
@@ -38,7 +37,6 @@
 #include "vmci_handle_array.h"
 #include "vmci_kernel_if.h"
 
-
 /*
  *  The DatagramQueueEntry is a queue header for the in-kernel VMCI
  *  datagram queues. It is allocated in non-paged memory, as the
@@ -55,6 +53,20 @@ typedef struct DatagramQueueEntry {
 } DatagramQueueEntry;
 
 
+/*
+ * The VMCIFilterState captures the state of all VMCI filters in one
+ * direction. The ranges array contains all filter list in a single
+ * memory chunk, and the filter list pointers in the VMCIProtoFilters
+ * point into the ranges array.
+ */
+
+typedef struct VMCIFilterState {
+   VMCIProtoFilters filters;
+   VMCIIdRange *ranges;
+   size_t rangesSize;
+} VMCIFilterState;
+
+
 struct VMCIContext {
    VMCIListItem       listItem;         /* For global VMCI list. */
    VMCIId             cid;
@@ -67,9 +79,9 @@ struct VMCIContext {
                                          * this context; e.g., VMX.
                                          */
    VMCILock           lock;             /*
-                                         * Locks datagramQueue, doorbellArray,
-                                         * pendingDoorbellArray and
-                                         * notifierArray.
+                                         * Locks datagramQueue, inFilters,
+                                         * doorbellArray, pendingDoorbellArray
+                                         * and notifierArray.
                                          */
    VMCIHandleArray    *queuePairArray;  /*
                                          * QueuePairs attached to.  The array of
@@ -96,6 +108,7 @@ struct VMCIContext {
                                          * registration/release during FSR.
                                          */
    VMCIGuestMemID     curGuestMemID;    /* ID of current registered guest mem */
+   VMCIFilterState    *inFilters;       /* Ingoing filters for VMCI traffic. */
 #endif
 #ifndef VMX86_SERVER
    Bool               *notify;          /* Notify flag pointer - hosted only. */
index f208f86bb103757b01ee25613a6fa70309e3ed56..8d154d4df922a3723131061b6e6ca13650980284 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2006-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2012 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -49,6 +49,7 @@ static int VMCIContextFireNotification(VMCIId contextID,
 #if defined(VMKERNEL)
 static void VMCIContextReleaseGuestMemLocked(VMCIContext *context,
                                              VMCIGuestMemID gid);
+static void VMCIContextInFilterCleanup(VMCIContext *context);
 #endif
 
 /*
@@ -331,6 +332,8 @@ VMCIContext_InitContext(VMCIId cid,                   // IN
       goto error;
    }
    context->curGuestMemID = INVALID_VMCI_GUEST_MEM_ID;
+
+   context->inFilters = NULL;
 #endif
 
    /* Inititialize host-specific VMCI context. */
@@ -501,6 +504,7 @@ VMCIContextFreeContext(VMCIContext *context)  // IN
    VMCIHandleArray_Destroy(context->pendingDoorbellArray);
    VMCI_CleanupLock(&context->lock);
 #if defined(VMKERNEL)
+   VMCIContextInFilterCleanup(context);
    VMCIMutex_Destroy(&context->guestMemMutex);
 #endif
    VMCIHost_ReleaseContext(&context->hostContext);
@@ -606,6 +610,18 @@ VMCIContext_EnqueueDatagram(VMCIId cid,        // IN: Target VM
    VMCIList_InitEntry(&dqEntry->listItem);
 
    VMCI_GrabLock(&context->lock, &flags);
+
+#if defined(VMKERNEL)
+   if (context->inFilters != NULL) {
+      if (VMCIFilterDenyDgIn(context->inFilters->filters, dg)) {
+         VMCI_ReleaseLock(&context->lock, flags);
+         VMCIContext_Release(context);
+         VMCI_FreeKernelMem(dqEntry, sizeof *dqEntry);
+         return VMCI_ERROR_NO_ACCESS;
+      }
+   }
+#endif
+
    /*
     * We put a higher limit on datagrams from the hypervisor.  If the pending
     * datagram is not from hypervisor, then we check if enqueueing it would
@@ -1993,6 +2009,13 @@ VMCIContext_NotifyDoorbell(VMCIId srcCID,                   // IN
    } else {
       VMCI_GrabLock(&dstContext->lock, &flags);
 
+#if defined(VMKERNEL)
+      if (dstContext->inFilters != NULL &&
+          VMCIFilterProtoDeny(dstContext->inFilters->filters, handle.resource,
+                              VMCI_FP_DOORBELL)) {
+         result = VMCI_ERROR_NO_ACCESS;
+      } else
+#endif // VMKERNEL
       if (!VMCIHandleArray_HasEntry(dstContext->doorbellArray, handle)) {
          result = VMCI_ERROR_NOT_FOUND;
       } else {
@@ -2531,3 +2554,87 @@ VMCIContext_ReleaseGuestMem(VMCIContext *context, // IN: Context structure
    VMCIMutex_Release(&context->guestMemMutex);
 #endif
 }
+
+#if defined(VMKERNEL)
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_FilterSet --
+ *
+ *      Sets an ingoing (host to guest) filter for the VMCI firewall of the
+ *      given context. If a filter list already exists for the given filter
+ *      entry, the old entry will be deleted. It is assumed that the list
+ *      can be used as is, and that the memory backing it will be freed by the
+ *      VMCI Context module once the filter is deleted.
+ *
+ * Results:
+ *      VMCI_SUCCESS on success,
+ *      VMCI_ERROR_NOT_FOUND if there is no active context linked to the cid,
+ *      VMCI_ERROR_INVALID_ARGS if a non-VM cid is specified.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+VMCIContext_FilterSet(VMCIId cid,                // IN
+                      VMCIFilterState *filters)  // IN
+{
+   VMCIContext *context;
+   VMCILockFlags flags;
+   VMCIFilterState *oldState;
+
+   if (!VMCI_CONTEXT_IS_VM(cid)) {
+      return VMCI_ERROR_INVALID_ARGS;
+   }
+
+   context = VMCIContext_Get(cid);
+   if (!context) {
+      return VMCI_ERROR_NOT_FOUND;
+   }
+
+   VMCI_GrabLock(&context->lock, &flags);
+
+   oldState = context->inFilters;
+   context->inFilters = filters;
+
+   VMCI_ReleaseLock(&context->lock, flags);
+   if (oldState) {
+      VMCIVMKDevFreeFilterState(oldState);
+   }
+   VMCIContext_Release(context);
+
+   return VMCI_SUCCESS;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContextInFilterCleanup --
+ *
+ *      When a context is destroyed, all filters will be deleted.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMCIContextInFilterCleanup(VMCIContext *context)
+{
+   if (context->inFilters != NULL) {
+      VMCIVMKDevFreeFilterState(context->inFilters);
+      context->inFilters = NULL;
+   }
+}
+
+#endif
+
index 7041a356277cac9500b2d7e416c5da4ee51db9da..2546097302af9f6042435ce3445c0a80aa6b0c33 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2006-2011 VMware, Inc. All rights reserved.
+ * Copyright (C) 2006-2012 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -36,6 +36,7 @@
 #include "vmci_handle_array.h"
 #include "vmci_infrastructure.h"
 #include "vmci_kernel_if.h"
+#include "vmciCommonInt.h"
 
 #define MAX_QUEUED_GUESTCALLS_PER_VM  100
 
@@ -115,6 +116,6 @@ void VMCIContext_SignalPendingDoorbells(VMCIId contextID);
 void VMCIContext_SignalPendingDatagrams(VMCIId contextID);
 
 int VMCIContextID2HostVmID(VMCIId contextID, void *hostVmID, size_t hostVmIDLen);
+int VMCIContext_FilterSet(VMCIId cid, VMCIFilterState *filterState);
 #endif
-
 #endif // _VMCI_CONTEXT_H_
index 5b222579d1b8ed582f53534d8972efc4a538734a..0953b8d843b353fda095097cb5020e378c5d9259 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef _VMCI_VERSION_H_
 #define _VMCI_VERSION_H_
 
-#define VMCI_DRIVER_VERSION          9.5.3.0
-#define VMCI_DRIVER_VERSION_COMMAS   9,5,3,0
-#define VMCI_DRIVER_VERSION_STRING   "9.5.3.0"
+#define VMCI_DRIVER_VERSION          9.5.4.0
+#define VMCI_DRIVER_VERSION_COMMAS   9,5,4,0
+#define VMCI_DRIVER_VERSION_STRING   "9.5.4.0"
 
 #endif /* _VMCI_VERSION_H_ */