Firejail: join fails with private-bin and an alternate (non-bash/sh) shell as default

Created on 28 Aug 2019  路  13Comments  路  Source: netblue30/firejail

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.

enhancement

All 13 comments

@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.

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.

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.

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"?

That sounds perfect :+1: .

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.

@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.

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.

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.

Error messages need some work #2743.

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

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, ...

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?

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.

Was this page helpful?
0 / 5 - 0 ratings