Q: Are device ids unique?
We're wondering whether we can safely authorise a device by its ID without risking authorising the wrong device.
Let me explain.
We're listening to USBGuard's signals and then determine whether to allow a device based on, e.g. whether the screen is locked. We also want to lock the screen and only authorise a device when the screen has been locked. So we postpone the authorisation of a device until the screen is fully locked.
Now there's a race: the device can disappear until we want to authorise it. That's not a problem in itself, but what we're wondering now is whether the device IDs are guaranteed to be unique or whether they, say, begin with "1" again after having reached UINT_MAX-2 which would give the attacker control over the device ID.
(yeah, I'm aware that UINT_MAX is big and that an attacker would need to increment quite many times. Probably too many times for any attack to be successful, i.e. with 50k re-plugs per second, it would still take a full day).
So what we're looking for, I guess, is some form of guarantee in the API that says something like "yeah, if you want to authorise device 2, you will only ever authorise this device or nothing". Bonus points if that's also part of the documentation.
This seems to be heavily related to https://github.com/USBGuard/usbguard/issues/39 which would probably avoid the problem altogether.
As a side quest: how does Linux behave if you re-plug a device 1000 times? AFAICS, the device number is a triple digit, i.e. /dev/bus/usb/001/001, so does it roll over after 999?
As a side quest: how does Linux behave if you re-plug a device 1000 times? AFAICS, the device number is a triple digit, i.e.
/dev/bus/usb/001/001, so does it roll over after 999?
I've experimented with qemu: It rolls over after 127.
I've done some experiments.
I've modified RuleSet::assignID() to return Rule::LastID - 10 + _id_next++.
https://github.com/USBGuard/usbguard/blob/ad7a9c60b3185b6761b2a0913f00a80eb41cfc59/src/Library/public/usbguard/RuleSet.cpp#L224-L227
Then I re-plugged a device a few times and observed the daemon's debug output as well as usbguard list-devices.
So what we're looking for, I guess, is some form of guarantee in the API that says something like "yeah, if you want to authorise device
2, you will only ever authorise this device or nothing". Bonus points if that's also part of the documentation.
The device IDs do indeed roll over.
Now I wonder: Is that desirable? Do we want to detect the overflow and.. bail out? Terminate the program?
What happens when you have a device with low ID (e.g. 1) and another device rolls over the maximum number resulting in the same number as the first one? If you modify the policy of the first device what happens?
- Both get modified?
- Only the first?
- Only the second? I will try to find some time to experiment with this as well, because as you mentioned this can be quite important.