Firejail: [enhancement] Allow whitelisting arbitrary directories

Created on 15 Jul 2018  路  26Comments  路  Source: netblue30/firejail

What do people think of adding the ability to whitelist files/directories within /usr (not _just_ files/directories within /usr/share/)?

enhancement

Most helpful comment

@chiraag-nataraj @netblue30 Did someone start working on this (whitelisting arbitrary top level directories)? Else I could give it a try, but it will take some time.

All 26 comments

Yes, that could be cool!

Is there any reason we restrict which directories we can whitelist under?

No, I just didn't know what directories are needed there, so I went for /usr/share only.

We can handle the way we did for all the other directories (/dev, /etc, /media, /mnt, /opt, /srv, /var, /tmp) and remove the handling of /usr/share.

The only reason is we have no idea what is

So I guess I'm a bit unclear on why exactly there are restrictions on which directories can be used in whitelist while the same is not true for blacklist.

Reference #2059 it shows a big problem with the whitelisting restrictions. Whitelisting the roots home directory (/root) as root user is not even possible

@t4777sd This is working for me:

root@smitsohu:~# firejail --whitelist=/root/.bashrc 
Reading profile /etc/firejail/server.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-passwdmgr.inc
Reading profile /etc/firejail/disable-programs.inc

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

Parent pid 6850, child pid 6851
The new log directory is /proc/6851/root/var/log
Child process initialized in 88.31 ms
root@smitsohu:~# ls -a
.  ..  .bashrc
root@smitsohu:~#

If whitelisting the entire home directory like firejail --whitelist=/root is what you want, try instead the --private option.

My real goal is to whitelist /home/[user]. Basically, I am running software as root that I want to sandbox. The software modifies /home/[user]. Is there any way to do this? I even tried changing the $HOME environment variable to make the current roots home the same as that user and it did not work.

I see. If --private doesn't suit your problem, and since you are running as root, you could just do firejail --tmpfs=/home/user.

Firejail doesn't read the $HOME environment variable, it instead extracts the home directory from /etc/passwd.

Is there a way to make the writes the software does persitent? I believe that tmpfs option will make a temporary file system at /home/user and therefore no writes done to the directory will be persistent. Correct me if I am wrong

@t4777sd Ok, now I understand what you want to do. You are right, all changes will be lost when the sandbox is closed. In the moment I don't see a solution with the current feature set.

@chiraag-nataraj @netblue30 Did someone start working on this (whitelisting arbitrary top level directories)? Else I could give it a try, but it will take some time.

@smitsohu Go for it by all means :)

@smitsohu Did you ever get a chance to work on this?

@chiraag-nataraj yes and no :)

I regarded it more as a mid-term goal.... for example the fs_tmpfs() function was written with whitelisting in mind, and I think supporting arbitrary home directories everywhere in Firejail would be another significant step into this direction.

But I see that progress is very slow currently, which is mainly due to time constraints. If someone wants to take this over feel free.

There is now a new branch with rewritten whitelist code, to support arbitrary top level directories (except /proc and /sys) and whitelist globbing. Also it fixes most of the still existing whitelist related issues.

In my experience it works quite well, but note that it breaks backwards compatibility: there is currently no support for mounting a tmpfs on a subdirectory, such as /sys/module or /usr/share or /run/user/$UID. This for example means that currently whitelist-usr-share-common.inc is broken _as-is_... as ad-hoc fix consider adding something like:

whitelist /usr/bin
whitelist /usr/lib*

Fully restoring the previous behavior probably still requires larger changes, but for the meantime there is something at least.

Guess it would be good to whitelist only in subdirectories in /usr, so the entrance barrier to develop sandbox configurations for /usr does not become too high.

There was a bug when there were no whitelist commands at all (now fixed).

One idea was to approach symbolic link creation more conservatively and then do away with current symlink restrictions (in the moment they are completely absent in the branch).

There are two end goals: 1) Firejail should never create a symbolic that does not exist in the real file system, 2) Firejail should try to rebuild symlink chains completely.

In practice, there is a requirement to always identify the top level directory, as we should not create symbolic links outside of a tmpfs, in the real file system. That's easy for the _first_ symlink in a path, because the top level directory is just the top level directory. It is complicated for symlink chains, with links pointing to relative paths.

The question now is if it would be ok to always replicate only the _first_ symbolic link in a path. And leave it to the user to fix broken symlink chains (the missing components would need to be explicitly whitelisted. There could be a detailed information or a warning).
The alternatives are a comparatively complicated parsing of relative paths, or of course just keeping the current restrictions as they are.

Opinions?

Just to summarize how things are handled currently: The symlink check is now run on the _last_ path element, and resolved and unresolved path must live in the same top level directory (there are exceptions). Now that I'm writing this down, I realize the differences are actually not that a big.

The current design has its limitations, too:

  • --whitelist=/dir/dir/link/dir/dir: no link is created at all, and resolved path/last dir is whitelisted, provided the top level directory is the same. It is possible to get the link by whitelisting /dir/dir/link, but this will whitelist the entire subtree, which is not what we were trying in the first place. There is a bug report somewhere with this issue, but I cannot seem to find it right now.
  • --whitelist=/dir/dir/link/dir/link creates a link, but link names in the middle are interpreted as directory names, so the path of the link is wrong. This is actually quite annoying.

I want to leave the original question about the best way forward open, but for the meantime I'm thinking to

always replicate only the first symbolic link in a path.

Where is the difference between this issue and #1130?

Any update on this?
I have a shared storage drive mounted under /home/storage and can't access it using firejail.
I also have symlinks to it in my home directory.

$ firejail --debug-whitelists --whitelist=/home/storage --noprofile ls /home/storage
Parent pid 19980, child pid 19981
Debug 423: new_name #/home/storage#, whitelist
Removed whitelist/nowhitelist path: whitelist /home/storage
    expanded: /home/storage
    real path: (null)
    realpath: No such file or directory
Child process initialized in 2.04 ms
ls: cannot access '/home/storage': No such file or directory

Whitelisting can not help you here, whitelisting is used to add restrictions not to remove restrictions. You need allusers here.

whitelisting is used to add restrictions not to remove restrictions

I thought whitelisting was to allow items explicitly set in a list -- in this case, to allow access to a certain path, right?

Just to clarify, /home/storage for me, is not a user; it is just a simple, shared directory.

I thought whitelisting was to allow items explicitly set in a list -- in this case, to allow access to a certain path, right?

It allows any item on that list, that's right. But whitelist also implies no access to anything not on the list. That's why it adds restrictions by requiring an explicit allow.

Just to clarify, /home/storage for me, is not a user; it is just a simple, shared directory.

AFAIK firejail don't care if /home/foo is a home-dir in /etc/passwd or not, because it is not relevant, to remove the other users-homes /home must be a tmpfs where $HOME is bind-mounted.

Oh, OK. I think I get now. /home is treated specially by firejail, and by default only the current user's home is visible in the sandbox -- that's why you mentioned allusers. This is my first time using firejail, so I don't know how it works, sorry.

firejail --allusers --noprofile ls /home/storage works.

But this doesn't.

$ firejail --debug-whitelists --whitelist=/home/storage --allusers --noprofile ls
Debug 423: new_name #/home/storage#, whitelist
real path /home/storage
Error: invalid whitelist path /home/storage
Error: proc 61526 cannot sync with peer: unexpected EOF

If I'm using an actual application, like qutebrowser, that means I can't use whitelists to restrict disk access, if I want to use this shared directory.

whitelisting is only supported in /dev, /etc, /media, /mnt, /opt, /run/user/$UID, /srv, /sys/module, /tmp, /usr/share and /var. If you try to whitelist /home/storage, it will fail therefore. If you just want to allow access to it, add allusers. If you want to add restrictions inside /home/storage, you can use a blacklist or mount it under e.g /mnt and add a whitelist.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fl-chris picture fl-chris  路  4Comments

yourcelf picture yourcelf  路  4Comments

Vincent43 picture Vincent43  路  3Comments

polyzen picture polyzen  路  4Comments

francoism90 picture francoism90  路  4Comments