Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[enhancement] Allow whitelisting arbitrary directories #2041

Closed
chiraag-nataraj opened this issue Jul 15, 2018 · 31 comments · Fixed by #4229
Closed

[enhancement] Allow whitelisting arbitrary directories #2041

chiraag-nataraj opened this issue Jul 15, 2018 · 31 comments · Fixed by #4229
Labels
enhancement New feature request

Comments

@chiraag-nataraj
Copy link
Collaborator

chiraag-nataraj commented Jul 15, 2018

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

@chiraag-nataraj chiraag-nataraj added the enhancement New feature request label Jul 15, 2018
@netblue30
Copy link
Owner

Yes, that could be cool!

@chiraag-nataraj
Copy link
Collaborator Author

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

@netblue30
Copy link
Owner

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

@chiraag-nataraj
Copy link
Collaborator Author

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.

@t4777sd
Copy link

t4777sd commented Jul 24, 2018

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

@chiraag-nataraj chiraag-nataraj changed the title [enhancement] Allow whitelisting directories within /usr [enhancement] Allow whitelisting arbitrary directories Jul 24, 2018
@smitsohu
Copy link
Collaborator

smitsohu commented Jul 24, 2018

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

@t4777sd
Copy link

t4777sd commented Jul 24, 2018

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.

@smitsohu
Copy link
Collaborator

smitsohu commented Jul 24, 2018

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.

@t4777sd
Copy link

t4777sd commented Jul 24, 2018

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

@smitsohu
Copy link
Collaborator

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

@smitsohu
Copy link
Collaborator

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

@chiraag-nataraj
Copy link
Collaborator Author

@smitsohu Go for it by all means :)

@chiraag-nataraj
Copy link
Collaborator Author

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

@smitsohu
Copy link
Collaborator

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

@smitsohu
Copy link
Collaborator

smitsohu commented Dec 2, 2019

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.

@smitsohu
Copy link
Collaborator

smitsohu commented Dec 2, 2019

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.

@smitsohu
Copy link
Collaborator

smitsohu commented Dec 8, 2019

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

@smitsohu
Copy link
Collaborator

smitsohu commented Dec 8, 2019

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?

@smitsohu
Copy link
Collaborator

smitsohu commented Dec 8, 2019

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.

@rusty-snake
Copy link
Collaborator

Where is the difference between this issue and #1130?

@FlyingWombat
Copy link

FlyingWombat commented Sep 13, 2020

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

@rusty-snake
Copy link
Collaborator

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

@FlyingWombat
Copy link

FlyingWombat commented Sep 15, 2020

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.

@rusty-snake
Copy link
Collaborator

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.

@FlyingWombat
Copy link

FlyingWombat commented Sep 17, 2020

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.

@rusty-snake
Copy link
Collaborator

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.

@tredondo
Copy link
Contributor

tredondo commented Mar 11, 2021

I have a VeraCrypt drive mounted under /v/. Is there a way to whitelist a certain path under it, like /v/some/dir?

I get "Error: invalid whitelist path" if I try to whitelist that path. By the way, that message could be more helpful... initially it made me think maybe I mistyped the directory.

@rusty-snake
Copy link
Collaborator

that message could be more helpful...

Error messages are still a big part (#2743).

Is there a way to whitelist a certain path under it, like /v/some/dir?

No, however you can use blacklisting:

noblacklist /v/some
blacklist /v/*
noblacklist /v/some/dir
blacklist /v/some/*

@tredondo
Copy link
Contributor

tredondo commented Mar 14, 2021

Thanks, that worked. But blacklisting /v/* means the program does see all the potentially sensitive file/directory names in /v, just can't access them. To prevent that, I tried noblacklist /v/some and blacklist /v, but that didn't work, I guess because all path elements from / to /v/some need to be visible?

@rusty-snake
Copy link
Collaborator

But blacklisting /v/* means the program does see all the potentially sensitive file/directory names in /v, just can't access them.

Correct so far. There's a second drawback: the blacklist is applied once when you start the sandbox, if you touch /v/foo later, it is not blacklisted.

I guess because all path elements from / to /v/some need to be visible?

noblacklist /foo/bar simply tells "ignore any later blacklist for /foo/bar".

@smitsohu
Copy link
Collaborator

Ok, there is a new experimental branch at https://github.com/smitsohu/firejail/tree/whitelist

It exploits the fact that we have full access to a directory as long as we have an open file descriptor - even if other directories or temporary filesystems are mounted on top later. This has the advantage that we don't need to manage mount stash locations.

All top level directories are allowed except /proc, /sys and /run. Exceptions are /sys/module and /run/user/$UID, in order to stay backwards compatible. Another special case is /usr, which is not treated as top level directory. Instead the /usr subdirectories (like /usr/share) are top level directories for the purpose of whitelisting.

One significant deviation from current whitelisting is that the symlink restrictions are gone. Everything else should be the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants