Index: /trunk/src/VBox/Additions/linux/module/vboxmod.c
===================================================================
--- /trunk/src/VBox/Additions/linux/module/vboxmod.c	(revision 15612)
+++ /trunk/src/VBox/Additions/linux/module/vboxmod.c	(revision 15613)
@@ -71,4 +71,5 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
+#include <iprt/memobj.h>
 #include <linux/miscdevice.h>
 #include <linux/poll.h>
@@ -364,4 +365,83 @@
 }
 
+/** Lock down R3 memory as needed for the HGCM call.  Copied from
+ * HGCMInternal.cpp and SysHlp.cpp */
+static int vboxadd_lock_hgcm_parms(void **ppvCtx, VBoxGuestHGCMCallInfo *pCallInfo)
+{
+    uint32_t cbParms = pCallInfo->cParms * sizeof (HGCMFunctionParameter);
+    int rc = VINF_SUCCESS;
+    unsigned iParm;
+    HGCMFunctionParameter *pParm;
+    memset (ppvCtx, 0, sizeof(void *) * pCallInfo->cParms);
+    if (cbParms)
+    {
+        /* Lock user buffers. */
+        pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
+
+        for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
+        {
+            switch (pParm->type)
+            {
+            case VMMDevHGCMParmType_LinAddr_Locked_In:
+                pParm->type = VMMDevHGCMParmType_LinAddr_In;
+                break;
+            case VMMDevHGCMParmType_LinAddr_Locked_Out:
+                pParm->type = VMMDevHGCMParmType_LinAddr_Out;
+                break;
+            case VMMDevHGCMParmType_LinAddr_Locked:
+                pParm->type = VMMDevHGCMParmType_LinAddr;
+                break;
+
+            case VMMDevHGCMParmType_LinAddr_In:
+            case VMMDevHGCMParmType_LinAddr_Out:
+            case VMMDevHGCMParmType_LinAddr:
+            {
+                RTR3PTR pv = (RTR3PTR)pParm->u.Pointer.u.linearAddr;
+                uint32_t u32Size = pParm->u.Pointer.size;
+                RTR0MEMOBJ MemObj;
+                rc = RTR0MemObjLockUser(&MemObj, pv, u32Size, NIL_RTR0PROCESS);
+                if (RT_SUCCESS(rc))
+                    ppvCtx[iParm] = MemObj;
+                else
+                    ppvCtx[iParm] = NIL_RTR0MEMOBJ;
+                break;
+            }
+            default:
+                /* make gcc happy */
+                break;
+            }
+            if (RT_FAILURE (rc))
+                break;
+        }
+    }
+    return RTErrConvertToErrno (rc);
+}
+
+/** Unlock R3 memory after the HGCM call.  Copied from HGCMInternal.cpp and
+ * SysHlp.cpp */
+static void vboxadd_unlock_hgcm_parms(void **ppvCtx, VBoxGuestHGCMCallInfo *pCallInfo)
+{
+    unsigned iParm;
+    /* Unlock user buffers. */
+    HGCMFunctionParameter *pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
+
+    for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pParm++)
+    {
+        if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
+            || pParm->type == VMMDevHGCMParmType_LinAddr_Out
+            || pParm->type == VMMDevHGCMParmType_LinAddr)
+        {
+            if (ppvCtx[iParm] != NULL)
+            {
+                RTR0MEMOBJ MemObj = (RTR0MEMOBJ)ppvCtx[iParm];
+                int rc = RTR0MemObjFree(MemObj, false);
+                AssertRC(rc);
+            }
+        }
+        else
+            Assert(!ppvCtx[iParm]);
+    }
+}
+
 /**
  * IOCTL handler.  Make an HGCM call.
@@ -376,6 +456,8 @@
 {
         VBoxGuestHGCMCallInfo *pInfo = NULL;
+        void *apvCtx[VBOX_HGCM_MAX_PARMS];
+        unsigned haveParms = 0;
         int rc = 0;
-        
+   
         pInfo = kmalloc(u32Size, GFP_KERNEL);
         if (pInfo == NULL)
@@ -392,4 +474,8 @@
                              u32Size));
             rc = -EINVAL;
+        }
+        if (rc >= 0) {
+            haveParms = 1;
+            rc = vboxadd_lock_hgcm_parms(apvCtx, pInfo);
         }
         if (rc >= 0) {
@@ -406,4 +492,6 @@
                 }
         }
+        if (haveParms)
+            vboxadd_unlock_hgcm_parms(apvCtx, pInfo);
         if (pInfo != NULL)
             kfree(pInfo);
@@ -424,4 +512,6 @@
 {
         VBoxGuestHGCMCallInfoTimed *pInfo = NULL;
+        void *apvCtx[VBOX_HGCM_MAX_PARMS];
+        unsigned haveParms = 0;
         int rc = 0;
         
@@ -440,4 +530,8 @@
                              u32Size));
             rc = -EINVAL;
+        }
+        if (rc >= 0) {
+            haveParms = 1;
+            rc = vboxadd_lock_hgcm_parms(apvCtx, &pInfo->info);
         }
         if (rc >= 0) {
@@ -455,4 +549,6 @@
                 }
         }
+        if (haveParms)
+            vboxadd_unlock_hgcm_parms(apvCtx, &pInfo->info);
         if (pInfo != NULL)
             kfree(pInfo);
