[GH-ISSUE #2934] join fails with private-bin and an alternate (non-bash/sh) shell as default #1832

Closed
opened 2026-05-05 08:29:52 -06:00 by gitea-mirror · 14 comments
Owner

Originally created by @veloute on GitHub (Aug 28, 2019).
Original GitHub issue: https://github.com/netblue30/firejail/issues/2934

as per https://github.com/netblue30/firejail/pull/2633#issuecomment-515280729

i've run into the problem of joining working about 40% of the time; out of the few i randomly just tested, keepassxc, mpv, hexchat and flameshot won't allow me to join (always with "execvp: No such file or directory" as the error) with zsh as the default shell.

Originally created by @veloute on GitHub (Aug 28, 2019). Original GitHub issue: https://github.com/netblue30/firejail/issues/2934 as per https://github.com/netblue30/firejail/pull/2633#issuecomment-515280729 > i've run into the problem of joining working about 40% of the time; out of the few i randomly just tested, keepassxc, mpv, hexchat and flameshot won't allow me to join (always with "execvp: No such file or directory" as the error) with zsh as the default shell.
gitea-mirror 2026-05-05 08:29:52 -06:00
Author
Owner

@ghost commented on GitHub (Aug 28, 2019):

@veloute The profiles you mention (keepassxc, mpv, hexchat and flameshot) all have a restricted private-bin, i.e. without including binaries zsh needs (or any other shell for that matter). Have you tried adding private-bin <whatever-zsh-needs> in foo.local yet? Another option is to add ignore private-bin (also in a foo.local file), but that will make the profile(s) slightly less tight... Perhaps it's not a bad idea to implement this whenever join is used with a profile containing private-bin.

<!-- gh-comment-id:525952682 --> @ghost commented on GitHub (Aug 28, 2019): @veloute The profiles you mention (keepassxc, mpv, hexchat and flameshot) all have a restricted `private-bin`, i.e. without including binaries zsh needs (or any other shell for that matter). Have you tried adding `private-bin <whatever-zsh-needs>` in foo.local yet? Another option is to add `ignore private-bin` (also in a foo.local file), but that will make the profile(s) slightly less tight... Perhaps it's not a bad idea to implement this whenever `join` is used with a profile containing `private-bin`.
Author
Owner

@veloute commented on GitHub (Aug 28, 2019):

that works.
should zsh be added to every private-bin line that has sh and bash or could something else be done? adding zsh to every line is the messier but only way i could think of that fixes the issue and doesn't potentially cause major holes in the profiles.

<!-- gh-comment-id:525955004 --> @veloute commented on GitHub (Aug 28, 2019): that works. should zsh be added to every private-bin line that has sh and bash or could something else be done? adding zsh to every line is the messier but only way i could think of that fixes the issue and doesn't potentially cause major holes in the profiles.
Author
Owner

@ghost commented on GitHub (Aug 28, 2019):

should zsh be added to every private-bin line that has sh and bash or could something else be done?

Until we fix this in the join option itself, that is your best bet I'm afraid. Marking this as a bug, so it might get more close attention. Perhaps you could change the issue to something like 'join fails with restrictive private-bin' or whatever you feel is appropriate. IMHO it's not only a zsh issue per se.

<!-- gh-comment-id:525957586 --> @ghost commented on GitHub (Aug 28, 2019): > should zsh be added to every private-bin line that has sh and bash or could something else be done? Until we fix this in the join option itself, that is your best bet I'm afraid. Marking this as a bug, so it might get more close attention. Perhaps you could change the issue to something like 'join fails with restrictive private-bin' or whatever you feel is appropriate. IMHO it's not only a zsh issue per se.
Author
Owner

@veloute commented on GitHub (Aug 28, 2019):

IMHO it's not only a zsh issue per se.

that's what i was thinking - users using alternate shells such as fish, csh, etc. would all (most likely) experience the same problem.
how about "join fails with private-bin and an alternate (non-bash/sh) shell as default"?

<!-- gh-comment-id:525958502 --> @veloute commented on GitHub (Aug 28, 2019): >IMHO it's not only a zsh issue per se. that's what i was thinking - users using alternate shells such as fish, csh, etc. would all (most likely) experience the same problem. how about "join fails with private-bin and an alternate (non-bash/sh) shell as default"?
Author
Owner

@ghost commented on GitHub (Aug 28, 2019):

That sounds perfect 👍 .

<!-- gh-comment-id:525958673 --> @ghost commented on GitHub (Aug 28, 2019): That sounds perfect :+1: .
Author
Owner

@rusty-snake commented on GitHub (Aug 29, 2019):

My shell: zsh
Here is an workaround:

[ Terminal 1 ]$ firejail --noprofile --name=test --private-bin=sleep,sl --shell=none sleep 5m
[ Terminal 2 ]$ firejail --shell=none --join=test sl
                         (  ) (@@) ( )  (@)  ()    @@    O     @     O     @      O
                     (@@@)
                 (    )
              (@@@@)

            (   )
        ====        ________                ___________
    _D _|  |_______/        \__I_I_____===__|_________|
     |(_)---  |   H\________/ |   |        =|___ ___|      _________________
     /     |  |   H  |  |     |   |         ||_| |_||     _|                \_____A
    |      |  |   H  |__--------------------| [___] |   =|                        |
    | ________|___H__/__|_____/[][]~\_______|       |   -|                        |
    |/ |   |-----------I_____I [][] []  D   |=======|____|________________________|_
  __/ =| o |=-~~\  /~~\  /~~\  /~~\ ____Y___________|__|__________________________|_
   |/-=|___|=O=====O=====O=====O   |_____/~\___/          |_D__D__D_|  |_D__D__D_|
    \_/      \__/  \__/  \__/  \__/      \_/               \_/   \_/    \_/   \_/

--shell=none allows you to start all programs specified in private-bin.

<!-- gh-comment-id:526061127 --> @rusty-snake commented on GitHub (Aug 29, 2019): My shell: zsh Here is an workaround: ``` [ Terminal 1 ]$ firejail --noprofile --name=test --private-bin=sleep,sl --shell=none sleep 5m [ Terminal 2 ]$ firejail --shell=none --join=test sl ( ) (@@) ( ) (@) () @@ O @ O @ O (@@@) ( ) (@@@@) ( ) ==== ________ ___________ _D _| |_______/ \__I_I_____===__|_________| |(_)--- | H\________/ | | =|___ ___| _________________ / | | H | | | | ||_| |_|| _| \_____A | | | H |__--------------------| [___] | =| | | ________|___H__/__|_____/[][]~\_______| | -| | |/ | |-----------I_____I [][] [] D |=======|____|________________________|_ __/ =| o |=-~~\ /~~\ /~~\ /~~\ ____Y___________|__|__________________________|_ |/-=|___|=O=====O=====O=====O |_____/~\___/ |_D__D__D_| |_D__D__D_| \_/ \__/ \__/ \__/ \__/ \_/ \_/ \_/ \_/ \_/ ``` `--shell=none` allows you to start all programs specified in `private-bin`.
Author
Owner

@smitsohu commented on GitHub (Aug 31, 2019):

@rusty-snake I think that's part of the solution. At least join-or-start should autodetect if the primary sandbox uses shell none, and do the same if it does.

Besides that there is the general question if it's a good idea to water down private-bin just to keep join working in all circumstances. I'm not sure if that's the way to go.

<!-- gh-comment-id:526811880 --> @smitsohu commented on GitHub (Aug 31, 2019): @rusty-snake I think that's part of the solution. At least `join-or-start` should autodetect if the primary sandbox uses `shell none`, and do the same if it does. Besides that there is the general question if it's a good idea to water down `private-bin` just to keep `join` working in all circumstances. I'm not sure if that's the way to go.
Author
Owner

@ghost commented on GitHub (Sep 1, 2019):

If this can be easily integrated into join-or-start that would suffice. I agree with @smitsohu that regular other usage of join should keep profiles as tight as possible, with or without private-bin. Just in case my earlier remarks were confusing.

<!-- gh-comment-id:526952535 --> @ghost commented on GitHub (Sep 1, 2019): If this can be easily integrated into `join-or-start` that would suffice. I agree with @smitsohu that regular other usage of join should keep profiles as tight as possible, with or without private-bin. Just in case my earlier remarks were confusing.
Author
Owner

@smitsohu commented on GitHub (Sep 5, 2019):

I think that's part of the solution. At least join-or-start should autodetect if the primary sandbox uses shell none, and do the same if it does.

Actually, turns out there is nothing to fix in join-or-start. It already handles shell none just right. But what would be good to have I think is an error message more helpful than this execve error code.

<!-- gh-comment-id:528380876 --> @smitsohu commented on GitHub (Sep 5, 2019): > I think that's part of the solution. At least join-or-start should autodetect if the primary sandbox uses shell none, and do the same if it does. Actually, turns out there is nothing to fix in `join-or-start`. It already handles `shell none` just right. But what would be good to have I think is an error message more helpful than this execve error code.
Author
Owner

@rusty-snake commented on GitHub (Sep 5, 2019):

Error messages need some work #2743.

Here we can do something like: please add $SHELL to private-bin or use shell none.

<!-- gh-comment-id:528388225 --> @rusty-snake commented on GitHub (Sep 5, 2019): Error messages need some work #2743. Here we can do something like: `please add $SHELL to private-bin or use shell none`.
Author
Owner

@smitsohu commented on GitHub (Aug 28, 2020):

It actually is possible to address it in join. We could open the shell just before entering the mount namespace, and then in the end execute the links in /proc/self/fd or use fexecve.

Then we have a shell, but a different question is how useful it will be. There is hardly any private-bin that includes ls, cat, ...

<!-- gh-comment-id:683061814 --> @smitsohu commented on GitHub (Aug 28, 2020): It actually _is_ possible to address it in join. We could open the shell just before entering the mount namespace, and then in the end execute the links in `/proc/self/fd` or use `fexecve`. Then we have a shell, but a different question is how useful it will be. There is hardly any `private-bin` that includes `ls`, `cat`, ...
Author
Owner

@smitsohu commented on GitHub (Nov 25, 2020):

It actually is possible to address it in join. We could open the shell just before entering the mount namespace, and then in the end execute the links in /proc/self/fd or use fexecve.

If that's the way to go, there are two problems:

  1. The shell's comm value will be either /proc/self/fd/N or the file descriptor number, and this is also how it will show up in top. It is only a cosmetic issue, maybe it is possible to address it with some LD_PRELOAD trick?
  2. In a perfect world we would support scripted shells and set O_CLOEXEC on the the shell descriptor in order to not leak it to the sandbox. The reality is that we can only have one or the other. In the words of the fexecve man page:

If fd refers to a script (i.e., it is an executable text file that names a script interpreter with a first line that begins with the characters #!) and the close-on-exec flag has been set for fd, the fexecve() fails with the error ENOENT. This error occurs because, by the time the script interpreter is executed, fd has already been closed because of the close-on-exec flag.

So a question is if Firejail can insist on a binary shell. Maybe there could be a second option, something like --shellargs, in order to optionally pass a script file?

<!-- gh-comment-id:733872195 --> @smitsohu commented on GitHub (Nov 25, 2020): > It actually is possible to address it in join. We could open the shell just before entering the mount namespace, and then in the end execute the links in /proc/self/fd or use fexecve. If that's the way to go, there are two problems: 1. The shell's comm value will be either `/proc/self/fd/N` or the file descriptor number, and this is also how it will show up in `top`. It is only a cosmetic issue, maybe it is possible to address it with some `LD_PRELOAD` trick? 2. In a perfect world we would support scripted shells _and_ set O_CLOEXEC on the the shell descriptor in order to not leak it to the sandbox. The reality is that we can only have one or the other. In the words of the `fexecve` man page: > If fd refers to a script (i.e., it is an executable text file that names a script interpreter with a first line that begins with the characters #!) and the close-on-exec flag has been set for fd, the fexecve() fails with the error ENOENT. This error occurs because, by the time the script interpreter is executed, fd has already been closed because of the close-on-exec flag. So a question is if Firejail can insist on a binary shell. Maybe there could be a second option, something like `--shellargs`, in order to optionally pass a script file?
Author
Owner

@smitsohu commented on GitHub (Dec 18, 2020):

Alright, there is now an experimental branch https://github.com/smitsohu/firejail/tree/smitsohu-shell

It allows users to join a sandbox and have a shell even if the shell is absent in the sandbox mount namespace. But as noted earlier this patch also adds new glitches, and I currently don't know how to avoid this:

  1. Injecting a scripted shell fails; presumably there are not so many people running firejail with a scripted shell, but it is a limitation. Works if both script and interpreter are accessible in the sandbox, same as now.
  2. The shell processes have funny names. Command lines look good though, and firejail's --tree/--list/--top options work just fine

Unfixed bug: If there is no bash shell in the sandbox, firejail --join works, but firejail --join bash does not.

<!-- gh-comment-id:747819719 --> @smitsohu commented on GitHub (Dec 18, 2020): Alright, there is now an experimental branch https://github.com/smitsohu/firejail/tree/smitsohu-shell It allows users to join a sandbox and have a shell even if the shell is absent in the sandbox mount namespace. But as noted earlier this patch also adds new glitches, and I currently don't know how to avoid this: 1. Injecting a scripted shell fails; presumably there are not so many people running firejail with a scripted shell, but it is a limitation. Works if both script and interpreter are accessible in the sandbox, same as now. 2. The shell processes have funny names. Command lines look good though, and firejail's --tree/--list/--top options work just fine Unfixed bug: If there is no bash shell in the sandbox, `firejail --join` works, but `firejail --join bash` does not.
Author
Owner

@rusty-snake commented on GitHub (Jun 20, 2022):

shell none becomes default (#5196).

<!-- gh-comment-id:1160569040 --> @rusty-snake commented on GitHub (Jun 20, 2022): `shell none` becomes default (#5196).
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#1832
No description provided.