[GH-ISSUE #5803] ssh: Couldn't open /dev/null: Permission denied #3096

Closed
opened 2026-05-05 09:44:02 -06:00 by gitea-mirror · 12 comments
Owner

Originally created by @fgpietersz on GitHub (Apr 25, 2023).
Original GitHub issue: https://github.com/netblue30/firejail/issues/5803

I had the same problem as with issue #1725 but with version 0.9.72

I tried what one of the users confirming it there tried, deleting ~/.adobe and ~/.macromedia and it fixed it. Looking at backup it looks to me that the cause was that these files were symlinks to /dev/null and the issue can be reproduced by recreating those links.

IIRC this used to be a way of preventing flash cookies. These are old files hanging around in privacy freaks (e.g. me!) home directories.

The relevant lines from running with firejail --debug seem to be:

Disable /dev/null (requested /home/graeme/.adobe)

and

Couldn't open /dev/null: Permission denied

I do not think .ssh needs to open these files (unless I try to sftp them or something) so I am not clear why there is an attempt to open them. Is there a way to ignore such things rather than stop the command running? They are blacklisted in disable-common.inc

Originally created by @fgpietersz on GitHub (Apr 25, 2023). Original GitHub issue: https://github.com/netblue30/firejail/issues/5803 I had the same problem as with issue #1725 but with version 0.9.72 I tried what one of the users confirming it there tried, deleting ~/.adobe and ~/.macromedia and it fixed it. Looking at backup it looks to me that the cause was that these files were symlinks to /dev/null and the issue can be reproduced by recreating those links. IIRC this used to be a way of preventing flash cookies. These are old files hanging around in privacy freaks (e.g. me!) home directories. The relevant lines from running with firejail --debug seem to be: Disable /dev/null (requested /home/graeme/.adobe) and Couldn't open /dev/null: Permission denied I do not think .ssh needs to open these files (unless I try to sftp them or something) so I am not clear why there is an attempt to open them. Is there a way to ignore such things rather than stop the command running? They are blacklisted in disable-common.inc
Author
Owner

@rusty-snake commented on GitHub (Apr 25, 2023):

IDK if you understood it correct, so the summary:

  • disable-common.inc contains a blacklist for ~/.adobe.
  • ~/.adobe is a symlink to /dev/null so firejail follows it and blacklists /dev/null
  • ssh starts, tries to access /dev/null, fails and says "I can not run in such an environment."
<!-- gh-comment-id:1522148243 --> @rusty-snake commented on GitHub (Apr 25, 2023): IDK if you understood it correct, so the summary: - disable-common.inc contains a blacklist for `~/.adobe`. - `~/.adobe` is a symlink to /dev/null so firejail follows it and blacklists /dev/null - ssh starts, tries to access /dev/null, fails and says "I can not run in such an environment."
Author
Owner

@rusty-snake commented on GitHub (Apr 25, 2023):

Is there a way to ignore such things rather than stop the command running?

Technically it works as intended because it does what you asked for. Nevermind following a symlink to /dev/null and blacklisting it is almost never wanted by the user so there could be an exception.

<!-- gh-comment-id:1522157125 --> @rusty-snake commented on GitHub (Apr 25, 2023): > Is there a way to ignore such things rather than stop the command running? Technically it works as intended because it does what you asked for. Nevermind following a symlink to `/dev/null` and blacklisting it is almost never wanted by the user so there could be an exception.
Author
Owner

@fgpietersz commented on GitHub (Apr 25, 2023):

IDK if you understood it correct, so the summary:

No, I did not properly understand what was happening. I am new to firejail ( I started using it yesterday) nor am I familiar with namespaces etc.. Thanks for the explanation.

If I understand you correctly because ~/.adobe is blacklisted, when firejail sees the symlink it blacklists /dev/null ?

It is confusing and not what I expected, but I see bugs relating to both the behaviour and the debug messages have been closed as notabug so I suppose this is too?

<!-- gh-comment-id:1522310218 --> @fgpietersz commented on GitHub (Apr 25, 2023): > IDK if you understood it correct, so the summary: No, I did not properly understand what was happening. I am new to firejail ( I started using it yesterday) nor am I familiar with namespaces etc.. Thanks for the explanation. If I understand you correctly because ~/.adobe is blacklisted, when firejail sees the symlink it blacklists /dev/null ? It is confusing and not what I expected, but I see bugs relating to both the behaviour and the debug messages have been closed as notabug so I suppose this is too?
Author
Owner

@rusty-snake commented on GitHub (Apr 25, 2023):

If I understand you correctly because ~/.adobe is blacklisted, when firejail sees the symlink it blacklists /dev/null ?

Correct.

It is confusing and not what I expected

In general following the symlink is more what users expect. Say you have ~/.gnupg symlinked to ~/gnupg because you do not want to work with a hidden folder, then following this symlink causes the blacklist still to work with your new path.

Because mount(2) defaults to following symlinks it's tricky (to impossible?) to blacklist a symlink. Since Linux 5.10 there is a MS_NOSYMFOLLOW flag, however it disables all symlinks as I understand. move_mount(2) (Linux 4.18) can do it if I'm correct.

<!-- gh-comment-id:1522330549 --> @rusty-snake commented on GitHub (Apr 25, 2023): > If I understand you correctly because ~/.adobe is blacklisted, when firejail sees the symlink it blacklists /dev/null ? Correct. > It is confusing and not what I expected In general following the symlink is more what users expect. Say you have `~/.gnupg` symlinked to `~/gnupg` because you do not want to work with a hidden folder, then following this symlink causes the blacklist still to work with your new path. Because `mount(2)` defaults to following symlinks it's tricky (to impossible?) to blacklist a symlink. Since Linux 5.10 there is a `MS_NOSYMFOLLOW` flag, however it disables all symlinks as I understand. `move_mount(2)` (Linux 4.18) can do it if I'm correct.
Author
Owner

@CRAG666 commented on GitHub (May 1, 2023):

Same problem when trying to use git with ssh

<!-- gh-comment-id:1529307369 --> @CRAG666 commented on GitHub (May 1, 2023): Same problem when trying to use git with ssh
Author
Owner

@fgpietersz commented on GitHub (May 1, 2023):

Same problem when trying to use git with ssh

Do you get the error message about /dev/null ? If so are there symlinks to it that are blocklisted? It will show in the output of firejail --debug git push (or pull or clone or whatever).

<!-- gh-comment-id:1529806646 --> @fgpietersz commented on GitHub (May 1, 2023): > Same problem when trying to use git with ssh Do you get the error message about /dev/null ? If so are there symlinks to it that are blocklisted? It will show in the output of firejail --debug git push (or pull or clone or whatever).
Author
Owner

@Changaco commented on GitHub (Apr 7, 2026):

I have a similar problem arising from the blacklist-nolog ${HOME}/.*_history line in disable-common.inc. It affects two different Python programs (github-backup and tox) that both attempt to open /dev/null in write mode.

Symlinks to /dev/null should probably be treated as a special case by firejail since they're a recurrent source of errors. It's never dangerous to allow full access to /dev/null, so firejail should only limit that access if explicitly and directly requested.

Python tracebacks
Traceback (most recent call last):
  File ".local/bin/github-backup", line 3, in <module>
    from github_backup.cli import main
  File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/cli.py", line 8, in <module>
    from github_backup.github_backup import (
    ...<10 lines>...
    )
  File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 36, in <module>
    FNULL = open(os.devnull, "w")
OSError: [Errno 30] Read-only file system: '/dev/null'
Traceback (most recent call last):
  File "/usr/bin/tox", line 8, in <module>
    sys.exit(run())
             ~~~^^
  File "/usr/lib/python3.14/site-packages/tox/run.py", line 23, in run
    result = main(sys.argv[1:] if args is None else args)
  File "/usr/lib/python3.14/site-packages/tox/run.py", line 42, in main
    state = setup_state(args)
  File "/usr/lib/python3.14/site-packages/tox/run.py", line 56, in setup_state
    options = get_options(*args)
  File "/usr/lib/python3.14/site-packages/tox/config/cli/parse.py", line 40, in get_options
    guess_verbosity, log_handler, source = _get_base(args)
                                           ~~~~~~~~~^^^^^^
  File "/usr/lib/python3.14/site-packages/tox/config/cli/parse.py", line 53, in _get_base
    Path(os.devnull).open("w", encoding=locale.getpreferredencoding(do_setlocale=False)) as file_handler,
    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 771, in open
    return io.open(self, mode, buffering, encoding, errors, newline)
           ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 30] Read-only file system: '/dev/null'
<!-- gh-comment-id:4197884623 --> @Changaco commented on GitHub (Apr 7, 2026): I have a similar problem arising from the `blacklist-nolog ${HOME}/.*_history` line in `disable-common.inc`. It affects two different Python programs (`github-backup` and `tox`) that both attempt to open `/dev/null` in write mode. Symlinks to `/dev/null` should probably be treated as a special case by firejail since they're a recurrent source of errors. It's never dangerous to allow full access to `/dev/null`, so firejail should only limit that access if explicitly and directly requested. <details> <summary>Python tracebacks</summary> ```python-traceback Traceback (most recent call last): File ".local/bin/github-backup", line 3, in <module> from github_backup.cli import main File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/cli.py", line 8, in <module> from github_backup.github_backup import ( ...<10 lines>... ) File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 36, in <module> FNULL = open(os.devnull, "w") OSError: [Errno 30] Read-only file system: '/dev/null' ``` ```python-traceback Traceback (most recent call last): File "/usr/bin/tox", line 8, in <module> sys.exit(run()) ~~~^^ File "/usr/lib/python3.14/site-packages/tox/run.py", line 23, in run result = main(sys.argv[1:] if args is None else args) File "/usr/lib/python3.14/site-packages/tox/run.py", line 42, in main state = setup_state(args) File "/usr/lib/python3.14/site-packages/tox/run.py", line 56, in setup_state options = get_options(*args) File "/usr/lib/python3.14/site-packages/tox/config/cli/parse.py", line 40, in get_options guess_verbosity, log_handler, source = _get_base(args) ~~~~~~~~~^^^^^^ File "/usr/lib/python3.14/site-packages/tox/config/cli/parse.py", line 53, in _get_base Path(os.devnull).open("w", encoding=locale.getpreferredencoding(do_setlocale=False)) as file_handler, ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/pathlib/__init__.py", line 771, in open return io.open(self, mode, buffering, encoding, errors, newline) ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ OSError: [Errno 30] Read-only file system: '/dev/null' ``` </details>
Author
Owner

@kmk3 commented on GitHub (Apr 10, 2026):

Here's an attempt to fix it:

@fgpietersz
@CRAG666
@Changaco

Does it fix the errors?

<!-- gh-comment-id:4225495797 --> @kmk3 commented on GitHub (Apr 10, 2026): Here's an attempt to fix it: * #7129 @fgpietersz @CRAG666 @Changaco Does it fix the errors?
Author
Owner

@kmk3 commented on GitHub (Apr 10, 2026):

@rusty-snake

Because mount(2) defaults to following symlinks it's tricky (to
impossible?) to blacklist a symlink. Since Linux 5.10 there is a
MS_NOSYMFOLLOW flag, however it disables all symlinks as I understand.
move_mount(2) (Linux 4.18) can do it if I'm correct.

I had the same concern with mount(2) + MS_NOSYMFOLLOW, but I managed to
make it work here with just open(2) + O_PATH|O_NOFOLLOW and passing the fd
to mount(2).

Not sure if it works on Linux <5.10.

<!-- gh-comment-id:4225516035 --> @kmk3 commented on GitHub (Apr 10, 2026): @rusty-snake > Because `mount(2)` defaults to following symlinks it's tricky (to > impossible?) to blacklist a symlink. Since Linux 5.10 there is a > `MS_NOSYMFOLLOW` flag, however it disables all symlinks as I understand. > `move_mount(2)` (Linux 4.18) can do it if I'm correct. I had the same concern with `mount(2)` + `MS_NOSYMFOLLOW`, but I managed to make it work here with just `open(2)` + `O_PATH|O_NOFOLLOW` and passing the fd to `mount(2)`. Not sure if it works on Linux <5.10.
Author
Owner

@Changaco commented on GitHub (Apr 11, 2026):

Does it fix the errors?

Yes.

Before the patch:

$ ln -s /dev/null ~/.fake_history
$ firejail python -c "open('/dev/null', 'w')"
Reading profile /etc/firejail/default.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-programs.inc
Reading profile /etc/firejail/landlock-common.inc

** Note: you can use --noprofile to disable default.profile **

firejail version 0.9.80

Parent pid 515237, child pid 515238
Warning: /sbin directory link was not blacklisted
Warning: /usr/sbin directory link was not blacklisted
Base filesystem installed in 28.03 ms
Child process initialized in 53.19 ms
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    open('/dev/null', 'w')
    ~~~~^^^^^^^^^^^^^^^^^^
OSError: [Errno 30] Read-only file system: '/dev/null'

Parent is shutting down, bye...

After building and installing the patched firejail:

$ firejail python -c "open('/dev/null', 'w')"
Reading profile /etc/firejail/default.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-programs.inc
Reading profile /etc/firejail/landlock-common.inc

** Note: you can use --noprofile to disable default.profile **

firejail version 0.9.81

Parent pid 515434, child pid 515435
Warning: /sbin directory link was not blacklisted
Warning: /usr/sbin directory link was not blacklisted
Base filesystem installed in 36.21 ms
Child process initialized in 75.78 ms

Parent is shutting down, bye...
<!-- gh-comment-id:4230326669 --> @Changaco commented on GitHub (Apr 11, 2026): > Does it fix the errors? Yes. Before the patch: ``` $ ln -s /dev/null ~/.fake_history $ firejail python -c "open('/dev/null', 'w')" Reading profile /etc/firejail/default.profile Reading profile /etc/firejail/disable-common.inc Reading profile /etc/firejail/disable-programs.inc Reading profile /etc/firejail/landlock-common.inc ** Note: you can use --noprofile to disable default.profile ** firejail version 0.9.80 Parent pid 515237, child pid 515238 Warning: /sbin directory link was not blacklisted Warning: /usr/sbin directory link was not blacklisted Base filesystem installed in 28.03 ms Child process initialized in 53.19 ms Traceback (most recent call last): File "<string>", line 1, in <module> open('/dev/null', 'w') ~~~~^^^^^^^^^^^^^^^^^^ OSError: [Errno 30] Read-only file system: '/dev/null' Parent is shutting down, bye... ``` After building and installing the patched firejail: ``` $ firejail python -c "open('/dev/null', 'w')" Reading profile /etc/firejail/default.profile Reading profile /etc/firejail/disable-common.inc Reading profile /etc/firejail/disable-programs.inc Reading profile /etc/firejail/landlock-common.inc ** Note: you can use --noprofile to disable default.profile ** firejail version 0.9.81 Parent pid 515434, child pid 515435 Warning: /sbin directory link was not blacklisted Warning: /usr/sbin directory link was not blacklisted Base filesystem installed in 36.21 ms Child process initialized in 75.78 ms Parent is shutting down, bye... ```
Author
Owner

@kmk3 commented on GitHub (Apr 13, 2026):

@Changaco

Does it fix the errors?

Yes.

Nice, thanks for testing.

<!-- gh-comment-id:4233029281 --> @kmk3 commented on GitHub (Apr 13, 2026): @Changaco > > Does it fix the errors? > > Yes. Nice, thanks for testing.
Author
Owner

@kmk3 commented on GitHub (Apr 13, 2026):

Because mount(2) defaults to following symlinks it's tricky (to
impossible?) to blacklist a symlink. Since Linux 5.10 there is a
MS_NOSYMFOLLOW flag, however it disables all symlinks as I understand.
move_mount(2) (Linux 4.18) can do it if I'm correct.

I had the same concern with mount(2) + MS_NOSYMFOLLOW, but I managed to
make it work here with just open(2) + O_PATH|O_NOFOLLOW and passing the
fd to mount(2).

Not sure if it works on Linux <5.10.

@Zopolis4

If you still use Linux 3.x (such as in #7108), can you test if the PR works?

<!-- gh-comment-id:4233031383 --> @kmk3 commented on GitHub (Apr 13, 2026): > > Because `mount(2)` defaults to following symlinks it's tricky (to > > impossible?) to blacklist a symlink. Since Linux 5.10 there is a > > `MS_NOSYMFOLLOW` flag, however it disables all symlinks as I understand. > > `move_mount(2)` (Linux 4.18) can do it if I'm correct. > > I had the same concern with `mount(2)` + `MS_NOSYMFOLLOW`, but I managed to > make it work here with just `open(2)` + `O_PATH|O_NOFOLLOW` and passing the > fd to `mount(2)`. > > > Not sure if it works on Linux <5.10. @Zopolis4 If you still use Linux 3.x (such as in #7108), can you test if the PR works? * #7129
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#3096
No description provided.