Some USB devices return BusTypeSas as their bus type instead of BusTypeUsb?

We have a minifilter/filter driver that uses both the minifilter instance setup callback and filter driver’s AddDevice to monitor USB connections and block some of them.

The problem is that on some cases, for example when the user connects its mobile phone to the USB port, when we send IOCTL_STORAGE_QUERY_PROPERTY to the corresponding device in either the minifilter instance setup callback or the filter driver AddDevice, it returns BusTypeSas instead of BusTypeUsb?

Although so far we only have witnessed this in VMware VMs, but are not sure if its related to VMware or the USB device? We also have tried to send the IOCTL_STORAGE_QUERY_PROPERTY to different devices on the stack (pdo, fdo, etc) but all of them return BusTypeSas.
And we get the hardwareID of the corresponding device object using IoGetDeviceProperty, we get something that starts with SCSI\VMware…

Why does this matter? It all depends on how the vendor exposed their device, and not all of them are consistent. Remember, to the VM, it’s not a USB device. It’s using a fake device that gets routed to the host system, and THERE it is a USB device.

@Tim_Roberts said:
Why does this matter? It all depends on how the vendor exposed their device, and not all of them are consistent. Remember, to the VM, it’s not a USB device. It’s using a fake device that gets routed to the host system, and THERE it is a USB device.

So how can we detect USB devices in such cases in our AddDevice or Minifilter InstanceSetup? We need to somehow detect whether its a USB device or not and then block or allow it based on some factors such as hardwareID, etc.

Because that’s never been done before??? Microsoft’s built-in Group Policy can block USB devices with relatively fine-grained control.

In your particular case, you would want to block it in the VM host, not in the VM itself. Right? By the time it’s in the VM, it’s too late.

@Tim_Roberts said:
Because that’s never been done before??? Microsoft’s built-in Group Policy can block USB devices with relatively fine-grained control.

In your particular case, you would want to block it in the VM host, not in the VM itself. Right? By the time it’s in the VM, it’s too late.

Are you saying that there is literally no way for us to detect whether we are getting a USB device or not in the AddDevice and instance setup callbacks? Assume that we do not want to use the Microsoft group policy for this. (Its a DeviceControl driver, we only want to allow certain USB devices only, and block the rest, without using Group Policy)

And note that the VMware case is just one example, there were some other rare cases where non virtualized computers were having a similar problem, but we were only able to reproduce it in VMware VMs.

The goal here is to basically block every possible external USB device (flash drive, mobile phone, etc), and only allow very specific USB devices (based on hardwareId, etc) to connect, and we need to detect whether or not a certain device is a external USB device or not in our AddDevice or minifilter instanceSetup callback. There has to be a way to detect whether or not a device is an external USB device or not!

What device or devices are you filtering?

@Mark_Roddy said:
What device or devices are you filtering?

We are installing the filter driver as the upper filter for Computer class {4d36e966-e325-11ce-bfc1-08002be10318}, and the minifilter via ActivtyMonitor class {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}.

Ok. Not sure what your minifilter is going to do for this problem, but your upper filter needs to be on top of usb controllers if you really want to filter only usb devices, otherwise you are at the mercy of the driver implementor. That would solve the problem of ‘is this a usb device’. You will have other problems, as it is complicated and you also have to start filtering usb hub devices as they provide usb devices not controllers.

Alternatively you could see if the device instance path is consistent using your current approach. It ought to start with 'USB'.

Are you saying that there is literally no way for us to detect whether we are getting a USB device or not in the AddDevice and instance setup callbacks?

Do you mean in the VM? You are completely at the mercy of your hypervisor. You aren’t talking to a real USB device. You are talking to a virtual device exposed by the virtual host. If it wants to expose USB drives as if they were punched card readers, then that’s what you’ll see.

@Mark_Roddy said:
Alternatively you could see if the device instance path is consistent using your current approach. It ought to start with 'USB'.

Shouldn’t the device instance path be treated opaque ?

Correct. The enumerator is exposed as a property without having to parse the instance string.

Shouldn’t the device instance path be treated opaque ?

Literally, yes. In practice, the device instance paths have not changed since Windows 98SE.

@Tim_Roberts said:
In practice, the device instance paths have not changed since Windows 98SE.

Irrelevant. It is a horrible and unprofessional methodology to write a driver based on observation alone. Drivers should always be written to the specifications and in this case Microsoft has warned never to decipher this format. Never mind it is completely unnecessary in this case anyway. Drivers that don’t follow the specs tend to blow up in time, especially if written by seasoned folks that rub elbows with microsoft because they have a false sense of security they know what’s going on and can safely outsmart the docs only later to get egg in their face. As another board member used to say, never install such a driver on my system.

@Mark_Roddy said:
Ok. Not sure what your minifilter is going to do for this problem, but your upper filter needs to be on top of usb controllers if you really want to filter only usb devices, otherwise you are at the mercy of the driver implementor. That would solve the problem of ‘is this a usb device’. You will have other problems, as it is complicated and you also have to start filtering usb hub devices as they provide usb devices not controllers.

So if we also install in the 36fc9e60-c465-11cf-8056-444553540000 ClassGUID, we can get the actual bus type (USB) when using IOCTL_STORAGE_QUERY_PROPERTY on the received pdo in the AddDevice? If so, why? I thought if we install as the UpperFilter of 4d36e966-e325-11ce-bfc1-08002be10318 ClassGUID we can intercept every USB connection as well, so why changing it to 36fc9e60-c465-11cf-8056-444553540000 will cause the target PDO to send us the proper BusType this time, instead of sending the SAS BusType? If I remember correctly, reason we chose 4d36e966-e325-11ce-bfc1-08002be10318 was that some USB devices wouldn’t show up in AddDevice if we used 36fc9e60-c465-11cf-8056-444553540000.

Alternatively you could see if the device instance path is consistent using your current approach. It ought to start with 'USB'.

Is this safe to do (using IoGetDevicePropertyData + DEVPKEY_Device_InstanceId) in the minifilter instanceSetup? And i assume we should send this to the device object that is returned from FltGetDiskDeviceObject, correct?

@Tim_Roberts said:
Because that’s never been done before??? Microsoft’s built-in Group Policy can block USB devices with relatively fine-grained control.

In your particular case, you would want to block it in the VM host, not in the VM itself. Right? By the time it’s in the VM, it’s too late.

But the problem is that when we use SetupDiGetDeviceRegistryProperty from user-mode, we can detect that device as a USB device, therefore there has to be a way to do it from kernel-mode as well.

Ok, as usual I some other suggestions everyone will hate:

  1. use a usb bus filter driver. You can then observe each new pdo as it is instantiated and you are guaranteed that it is a pdo on a usb bus. Very complicated to implement because a) it is the usb architecture, b) bus filters are supported but undocumented.
  2. defer the management decision until the device is instantiated and then do everything to identify the device from user mode where it is all doc’d and supported. Ugly when you disable the device.
  3. ignore the ‘don’t look at the instance path prefix’ advice. Some people here will refuse to install your product.
1 Like

Tim is correct - whatever lie your hypervisor supplies is all you have to go on. Even for physical hardware, how will you differentiate between an internal USB drive and an external one? Some motherboards have internal USB devices for all kinds of things because its cheep and easy