[GH-ISSUE #1990] firefox: Yubikey u2f does not work if plugged in after launching (private-dev) #1341

Closed
opened 2026-05-05 07:53:46 -06:00 by gitea-mirror · 19 comments
Owner

Originally created by @chiraag-nataraj on GitHub (Jun 11, 2018).
Original GitHub issue: https://github.com/netblue30/firejail/issues/1990

So as documented in a bunch of issues (#1553, #1381), private-dev is broken with U2F. But I worked around that by using a whitelist instead in my Firefox profile, and it works.

However, I ran into a separate issue just now. The Yubikey is put into a different mode if I plug it in after starting the browser. So normally, it should use U2F authentication when requested. However, I think it gets stuck in OTP mode if I plug in the Yubikey after starting Firefox. If I plug it in before starting the browser, everything works as expected. But if I take it out and plug it back in later (say, because I want to authenticate another site), I run into the same issue. I will try removing my whitelist /dev entries to see if that fixes the issue.

Originally created by @chiraag-nataraj on GitHub (Jun 11, 2018). Original GitHub issue: https://github.com/netblue30/firejail/issues/1990 So as documented in a bunch of issues (#1553, #1381), `private-dev` is broken with U2F. But I worked around that by using a `whitelist` instead in my Firefox profile, and it works. However, I ran into a separate issue just now. The Yubikey is put into a different mode if I plug it in _after_ starting the browser. So normally, it should use U2F authentication when requested. However, I think it gets stuck in OTP mode if I plug in the Yubikey after starting Firefox. If I plug it in before starting the browser, everything works as expected. But if I take it out and plug it back in later (say, because I want to authenticate another site), I run into the same issue. I will try removing my `whitelist /dev` entries to see if that fixes the issue.
gitea-mirror 2026-05-05 07:53:46 -06:00
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Yup, commenting out the whitelist /dev entries fixes the problem. I'm not quite sure what's going on, since I whitelisted the required /dev/hidraw* devices.

<!-- gh-comment-id:396270180 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Yup, commenting out the `whitelist /dev` entries fixes the problem. I'm not quite sure what's going on, since I whitelisted the required `/dev/hidraw*` devices.
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Huh, I'm going to try whitelisting /dev/usb/hiddev*

<!-- gh-comment-id:396271229 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Huh, I'm going to try whitelisting `/dev/usb/hiddev*`
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Okay, I see what's happening. When I whitelisted /dev/usb/ and /dev/usb/hiddev0, those devices existed upon startup. However, when I took the Yubikey out and plugged it back in, /dev/usb/hiddev0 failed to reappear. Given that this file is created when the Yubikey is plugged in, this is probably why authentication no longer works when you take out the Yubikey and plug it back in.

@netblue30 Do you have any idea why the whitelisted file is not re-appearing when it is re-created? Or rather, is there any way we can enable this? This would probably need some type of inotify system and a new command-line/profile option (something like --watch=<file or directory>) which would watch for and react to changes. Thoughts?

<!-- gh-comment-id:396274477 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Okay, I see what's happening. When I whitelisted `/dev/usb/` and `/dev/usb/hiddev0`, those devices existed upon startup. However, when I took the Yubikey out and plugged it back in, `/dev/usb/hiddev0` failed to reappear. Given that this file is created when the Yubikey is plugged in, this is probably why authentication no longer works when you take out the Yubikey and plug it back in. @netblue30 Do you have any idea why the whitelisted file is not re-appearing when it is re-created? Or rather, is there any way we can enable this? This would probably need some type of inotify system and a new command-line/profile option (something like `--watch=<file or directory>`) which would watch for and react to changes. Thoughts?
Author
Owner

@Vincent43 commented on GitHub (Jun 11, 2018):

I think the problem is that firejail drops all privileges and can't modify sandbox after it was created. You have to either plug the token before starting sandbox or add ignore private-dev to local modifications.

<!-- gh-comment-id:396280132 --> @Vincent43 commented on GitHub (Jun 11, 2018): I think the problem is that firejail drops all privileges and can't modify sandbox after it was created. You have to either plug the token before starting sandbox or add `ignore private-dev` to local modifications.
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Hmmm. I guess the problem is that with either whitelist or private-dev, a new view of the filesystem is created which is effectively static. But if that's the case, why is /dev/usb/hiddev0 disappearing after I disconnect it? Shouldn't the device file remain even if the device itself is disconnected?

<!-- gh-comment-id:396281095 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Hmmm. I guess the problem is that with either `whitelist` or `private-dev`, a new view of the filesystem is created which is effectively static. But if that's the case, why is `/dev/usb/hiddev0` disappearing after I disconnect it? Shouldn't the device file remain even if the device itself is disconnected?
Author
Owner

@Vincent43 commented on GitHub (Jun 11, 2018):

I think it's better to say that new view of filesystem is subset of the old view at the time it's created. So if existing device is deleted from host it's also deleted from sandbox but when new device is added to host the sandbox remains unaffected.

<!-- gh-comment-id:396375131 --> @Vincent43 commented on GitHub (Jun 11, 2018): I think it's better to say that new view of filesystem is subset of the old view at the time it's created. So if existing device is deleted from host it's also deleted from sandbox but when new device is added to host the sandbox remains unaffected.
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Hmm, and this is a feature of mount namespaces I take it?

<!-- gh-comment-id:396419862 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Hmm, and this is a feature of mount namespaces I take it?
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 11, 2018):

Looking at the mount_namespaces man page, couldn't we use the MS_SHARED propagation type? That is, use the MS_SHARED propagation type only on those specific files and directories that we whitelist (specifically for private-dev or whitelist on files/directories in /dev)?

<!-- gh-comment-id:396421961 --> @chiraag-nataraj commented on GitHub (Jun 11, 2018): Looking at the `mount_namespaces` man page, couldn't we use the `MS_SHARED` propagation type? That is, use the `MS_SHARED` propagation type only on those specific files and directories that we whitelist (specifically for `private-dev` or `whitelist` on files/directories in `/dev`)?
Author
Owner

@netblue30 commented on GitHub (Jun 12, 2018):

However, when I took the Yubikey out and plugged it back in, /dev/usb/hiddev0 failed to reappear.

That's the mount namespace, it has its own mount table. When you plug in a USB device it goes into the default mount table and it will not be propagated to all other namespaces.

There is this list of devices: https://github.com/netblue30/firejail/blob/master/src/firejail/fs_dev.c#L51

What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc.

<!-- gh-comment-id:396435084 --> @netblue30 commented on GitHub (Jun 12, 2018): > However, when I took the Yubikey out and plugged it back in, /dev/usb/hiddev0 failed to reappear. That's the mount namespace, it has its own mount table. When you plug in a USB device it goes into the default mount table and it will not be propagated to all other namespaces. There is this list of devices: https://github.com/netblue30/firejail/blob/master/src/firejail/fs_dev.c#L51 What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc.
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc.

Hmmm, that would go part-way towards solving this. But unlike with many other things, Yubikeys (and other U2F hardware devices) are things we repeatedly plug in and take out (leaving them in all the time can be a security risk, since it means that if the laptop is stolen, so is the key). As I mentioned above, there seem to be different mount propagation modes, and the behavior you're describing would be the default (slave?) mode iirc. Would it be possible to set up a shared mount for just the specific devices that are whitelisted? Or is that fundamentally impossible?

<!-- gh-comment-id:396436052 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): > What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc. Hmmm, that would go part-way towards solving this. But unlike with many other things, Yubikeys (and other U2F hardware devices) are things we repeatedly plug in and take out (leaving them in all the time can be a security risk, since it means that if the laptop is stolen, so is the key). As I mentioned above, there seem to be different mount propagation modes, and the behavior you're describing would be the default (slave?) mode iirc. Would it be possible to set up a shared mount for just the specific devices that are whitelisted? Or is that fundamentally impossible?
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

Also, the key parts seem to actually be the things in /dev/usb (i.e. /dev/usb/hiddev0 in my example above), since /dev/hidraw* seem to stay around even after I take out the Yubikey?

<!-- gh-comment-id:396444800 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): Also, the key parts seem to actually be the things in `/dev/usb` (i.e. `/dev/usb/hiddev0` in my example above), since `/dev/hidraw*` seem to stay around even after I take out the Yubikey?
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

Huh, this is actually really interesting. I tried using unshare to play around with mount namespaces. It seems that if I use unshare to create a private,slave mount namespace (through sudo unshare -m --propagation slave /bin/bash), it still recognizes when the Yubikey is plugged back in (consistent with the manpage, which states that "When a mount point is a slave, mount and unmount events propagate into this mount point from the (master) shared peer group of which it was formerly a member. Mount and unmount events under this mount point do not propagate to any peer."

That is, mount events from the master (in this case, that should be the global namespace, right?) should propagate into the slave namespace, while mount events in the slave shouldn't propagate back. But that seems to not be happening, even though this is a private,slave namespace. Does this have to do with the fact that we're creating mount namespaces for individual files?

<!-- gh-comment-id:396446762 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): Huh, this is actually really interesting. I tried using `unshare` to play around with mount namespaces. It seems that if I use `unshare` to create a `private,slave` mount namespace (through `sudo unshare -m --propagation slave /bin/bash`), it still recognizes when the Yubikey is plugged back in (consistent with the manpage, which states that "When a mount point is a slave, mount and unmount events propagate into this mount point from the (master) shared peer group of which it was formerly a member. Mount and unmount events under this mount point do not propagate to any peer." That is, mount events from the master (in this case, that should be the global namespace, right?) should propagate into the slave namespace, while mount events in the slave shouldn't propagate back. But that seems to not be happening, even though this is a `private,slave` namespace. Does this have to do with the fact that we're creating mount namespaces for individual files?
Author
Owner

@netblue30 commented on GitHub (Jun 12, 2018):

Try the latest from main. I am bringing in by default /dev/usb in --private-bin:

2b4afcfb0a

<!-- gh-comment-id:396565098 --> @netblue30 commented on GitHub (Jun 12, 2018): Try the latest from main. I am bringing in by default /dev/usb in --private-bin: https://github.com/netblue30/firejail/commit/2b4afcfb0ae77ffd40e665efdada274d804678bc
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

Nope. I think we need to whitelist /dev/hidraw* as well? I'm going to add it and try and report back.

<!-- gh-comment-id:396566415 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): Nope. I think we need to whitelist `/dev/hidraw*` as well? I'm going to add it and try and report back.
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

Latest commit should fix it
78011fbc92

<!-- gh-comment-id:396567992 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): Latest commit should fix it 78011fbc922e4dc69f41b107cefee8bbd26d11bc
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

I suppose there's really nothing we can do about the device not re-appearing when we plug it back in, is there?

<!-- gh-comment-id:396568408 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): I suppose there's really nothing we can do about the device not re-appearing when we plug it back in, is there?
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

Also added a --nousb option to the command args and nousb option for the profile.

197bcc86c1

<!-- gh-comment-id:396595875 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): Also added a `--nousb` option to the command args and `nousb` option for the profile. 197bcc86c1a1f4c75d6a42a850e0619b3268db1e
Author
Owner

@chiraag-nataraj commented on GitHub (Jun 12, 2018):

If there's no way to solve the mount propagation issue, I think I can close this.

<!-- gh-comment-id:396596395 --> @chiraag-nataraj commented on GitHub (Jun 12, 2018): If there's no way to solve the mount propagation issue, I think I can close this.
Author
Owner

@kubrickfr commented on GitHub (Jul 3, 2018):

Would it be possible to add a udev rule to have the /dev/ file permanently in place even if the device is not connected?

<!-- gh-comment-id:402233714 --> @kubrickfr commented on GitHub (Jul 3, 2018): Would it be possible to add a udev rule to have the /dev/ file permanently in place even if the device is not connected?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#1341
No description provided.