Index: /trunk/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp	(revision 36994)
+++ /trunk/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp	(revision 36995)
@@ -114,4 +114,7 @@
      * available we fall back to USBFS.
      * In the event of both failing, an appropriate error will be returned.
+     * The user may also specify a method and root using the VBOX_USB and
+     * VBOX_USB_ROOT environment variables.  In this case we don't check
+     * the root they provide for validity.
      */
     bool fUsbfsChosen = false, fSysfsChosen = false;
Index: /trunk/src/VBox/Main/testcase/tstUSBProxyLinux.cpp
===================================================================
--- /trunk/src/VBox/Main/testcase/tstUSBProxyLinux.cpp	(revision 36994)
+++ /trunk/src/VBox/Main/testcase/tstUSBProxyLinux.cpp	(revision 36995)
@@ -82,23 +82,42 @@
     bool fUsbfsAccessible;
     int rcMethodInit;
-    int rcExpected;
     const char *pcszDevicesRootExpected;
     bool fUsingUsbfsExpected;
+    int rcExpected;
 } s_testEnvironment[] =
 {
-    { "sysfs", "/dev/bus/usb", NULL, false, NULL, false, VINF_SUCCESS, VINF_SUCCESS, "/dev/bus/usb", false },
-    { "sysfs", "/dev/bus/usb", NULL, false, NULL, false, VERR_NO_MEMORY, VERR_NO_MEMORY, "/dev/bus/usb", false },
-    { "sysfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VINF_SUCCESS, VINF_SUCCESS, "/dev/bus/usb", false },
-    { "sysfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VERR_NO_MEMORY, VERR_NO_MEMORY, "/dev/bus/usb", false },
-    { "sysfs", NULL, "/dev/vboxusb", true, NULL, false, VINF_SUCCESS, VINF_SUCCESS, "/dev/vboxusb", false },
-    { "usbfs", "/dev/bus/usb", NULL, false, NULL, false, VINF_SUCCESS, VINF_SUCCESS, "/dev/bus/usb", true },
-    { "usbfs", "/dev/bus/usb", NULL, false, NULL, false, VERR_NO_MEMORY, VERR_NO_MEMORY, "/dev/bus/usb", true },
-    { "usbfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VINF_SUCCESS, VINF_SUCCESS, "/dev/bus/usb", true },
-    { "usbfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VERR_NO_MEMORY, VERR_NO_MEMORY, "/dev/bus/usb", true },
-    { "usbfs", NULL, NULL, false, "/proc/bus/usb", true, VINF_SUCCESS, VINF_SUCCESS, "/proc/bus/usb", true },
-    { NULL, NULL, "/dev/vboxusb", false, "/proc/bus/usb", false, VERR_NO_MEMORY, VERR_VUSB_USB_DEVICE_PERMISSION, "", true },
-    { NULL, NULL, "/dev/vboxusb", true, "/proc/bus/usb", false, VERR_NO_MEMORY, VERR_NO_MEMORY, "/dev/vboxusb", false },
-    { NULL, NULL, NULL, false, "/proc/bus/usb", false, VERR_NO_MEMORY, VERR_VUSB_USBFS_PERMISSION, "", true },
-    { NULL, NULL, NULL, false, "/proc/bus/usb", true, VERR_NO_MEMORY, VERR_NO_MEMORY, "/proc/bus/usb", true }
+    /* "sysfs" and root in the environment */
+    { "sysfs", "/dev/bus/usb", NULL, false, NULL, false, VINF_SUCCESS, "/dev/bus/usb", false, VINF_SUCCESS },
+    /* "sysfs" and root in the environment, method-specific init failed */
+    { "sysfs", "/dev/bus/usb", NULL, false, NULL, false, VERR_NO_MEMORY, "/dev/bus/usb", false, VERR_NO_MEMORY },
+    /* "sysfs" and bad root in the environment (should succeed as we don't
+     * do checks if the user specifies everything) */
+    { "sysfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VINF_SUCCESS, "/dev/bus/usb", false, VINF_SUCCESS },
+    /* "sysfs" and bad root in the environment, method-specific init failed */
+    { "sysfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VERR_NO_MEMORY, "/dev/bus/usb", false, VERR_NO_MEMORY },
+    /* "sysfs" and no root in the environment */
+    { "sysfs", NULL, "/dev/vboxusb", true, NULL, false, VINF_SUCCESS, "/dev/vboxusb", false, VINF_SUCCESS },
+    /* "usbfs" and root in the environment */
+    { "usbfs", "/dev/bus/usb", NULL, false, NULL, false, VINF_SUCCESS, "/dev/bus/usb", true, VINF_SUCCESS },
+    /* "usbfs" and root in the environment, method-specific init failed */
+    { "usbfs", "/dev/bus/usb", NULL, false, NULL, false, VERR_NO_MEMORY, "/dev/bus/usb", true, VERR_NO_MEMORY },
+    /* "usbfs" and bad root in the environment (should succeed as we don't
+     * do checks if the user specifies everything) */
+    { "usbfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VINF_SUCCESS, "/dev/bus/usb", true, VINF_SUCCESS },
+    /* "usbfs" and bad root in the environment, method-specific init failed */
+    { "usbfs", "/dev/bus/usb", "/dev/usbvbox", false, "/proc/usb/bus", false, VERR_NO_MEMORY, "/dev/bus/usb", true, VERR_NO_MEMORY },
+    /* "usbfs" and no root in the environment */
+    { "usbfs", NULL, NULL, false, "/proc/bus/usb", true, VINF_SUCCESS, "/proc/bus/usb", true, VINF_SUCCESS },
+    /* No environment, sysfs and usbfs available but without access
+     * permissions. */
+    { NULL, NULL, "/dev/vboxusb", false, "/proc/bus/usb", false, VERR_NO_MEMORY, "", true, VERR_VUSB_USB_DEVICE_PERMISSION },
+    /* No environment, sysfs and usbfs available, access permissions for sysfs,
+     * method-specific init failed. */
+    { NULL, NULL, "/dev/vboxusb", true, "/proc/bus/usb", false, VERR_NO_MEMORY, "/dev/vboxusb", false, VERR_NO_MEMORY },
+    /* No environment, usbfs available but without access permissions. */
+    { NULL, NULL, NULL, false, "/proc/bus/usb", false, VERR_NO_MEMORY, "", true, VERR_VUSB_USBFS_PERMISSION },
+    /* No environment, usbfs available with access permissions, method-specific
+     * init failed. */
+    { NULL, NULL, NULL, false, "/proc/bus/usb", true, VERR_NO_MEMORY, "/proc/bus/usb", true, VERR_NO_MEMORY }
 };
 
@@ -118,13 +137,13 @@
         HRESULT hrc = test.init();
         RTTESTI_CHECK_MSG(hrc == S_OK,
-                           ("init() returned 0x%x on line %i!\n", hrc, i));
+                           ("init() returned 0x%x (test index %i)!\n", hrc, i));
         int rc = test.getLastError();
         RTTESTI_CHECK_MSG(rc == s_testEnvironment[i].rcExpected,
-                          ("getLastError() returned %Rrc on line %i instead of %Rrc!\n",
+                          ("getLastError() returned %Rrc (test index %i) instead of %Rrc!\n",
                            rc, i, s_testEnvironment[i].rcExpected));
         const char *pcszDevicesRoot = test.testGetDevicesRoot();
         RTTESTI_CHECK_MSG(!RTStrCmp(pcszDevicesRoot,
                                s_testEnvironment[i].pcszDevicesRootExpected),
-                          ("testGetDevicesRoot() returned %s on line %i instead of %s!\n",
+                          ("testGetDevicesRoot() returned %s (test index %i) instead of %s!\n",
                            pcszDevicesRoot, i,
                            s_testEnvironment[i].pcszDevicesRootExpected));
@@ -132,5 +151,5 @@
         RTTESTI_CHECK_MSG(   fUsingUsbfs
                           == s_testEnvironment[i].fUsingUsbfsExpected,
-                          ("testGetUsingUsbfs() returned %RTbool on line %i instead of %RTbool!\n",
+                          ("testGetUsingUsbfs() returned %RTbool (test index %i) instead of %RTbool!\n",
                            fUsingUsbfs, i,
                            s_testEnvironment[i].fUsingUsbfsExpected));
@@ -147,10 +166,21 @@
 } s_testCheckDeviceRoot[] =
 {
+    /* /dev/vboxusb accessible -> device nodes method available */
     { { NULL }, { "/dev/vboxusb" }, "/dev/vboxusb", true, true },
+    /* /dev/vboxusb present but not accessible -> device nodes method not
+     * available */
     { { NULL }, { NULL }, "/dev/vboxusb", true, false },
+    /* /proc/bus/usb available but empty -> usbfs method available (we can't
+     * really check in this case) */
     { { NULL }, { NULL }, "/proc/bus/usb", false, true },
+    /* /proc/bus/usb available, one inaccessible device -> usbfs method not
+     * available */
     { { "/proc/bus/usb/001/001" }, { NULL }, "/proc/bus/usb", false, false },
+    /* /proc/bus/usb available, one device of two inaccessible -> usbfs method
+     * not available */
     { { "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
       { "/proc/bus/usb/001/001" }, "/proc/bus/usb", false, false },
+    /* /proc/bus/usb available, two accessible devices -> usbfs method
+     * available */
     { { "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
       { "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
@@ -172,5 +202,5 @@
         RTTESTI_CHECK_MSG(   fAvailable
                           == s_testCheckDeviceRoot[i].fAvailableExpected,
-                           ("USBProxyLinuxCheckDeviceRoot() returned %RTbool on line %i instead of %RTbool!\n",
+                           ("USBProxyLinuxCheckDeviceRoot() returned %RTbool (test index %i) instead of %RTbool!\n",
                             fAvailable, i,
                             s_testCheckDeviceRoot[i].fAvailableExpected));
