[GH-ISSUE #3189] Sharing data through /run subdirs #1994

Closed
opened 2026-05-05 08:39:33 -06:00 by gitea-mirror · 11 comments
Owner

Originally created by @jonleivent on GitHub (Jan 27, 2020).
Original GitHub issue: https://github.com/netblue30/firejail/issues/3189

The fact that --private-tmp does not create a private /run should be documented better. It seems that unless one blacklists or read-only's subdirs of /run (careful not to do so for /run/firejail), then there are always ways that a firejailed app can share data through items in /run with other apps outside the jail, regardless of the other firejail options used. I think many would expect --private-tmp to cover /run, since /run is just a better organized alternative to /tmp.

Here's a scenario: A user sets up two firejails for two apps. One jailed app given read-only access to sensitive data but is cut off from all network access. The other is given network access but is cut off from reading sensitive data. Those two apps can communicate through the /run/user/1000/pulse dir, for instance, and tunnel the sensitive data out to the network.

Perhaps there should be a --private-run option?

Originally created by @jonleivent on GitHub (Jan 27, 2020). Original GitHub issue: https://github.com/netblue30/firejail/issues/3189 The fact that --private-tmp does not create a private /run should be documented better. It seems that unless one blacklists or read-only's subdirs of /run (careful not to do so for /run/firejail), then there are always ways that a firejailed app can share data through items in /run with other apps outside the jail, regardless of the other firejail options used. I think many would expect --private-tmp to cover /run, since /run is just a better organized alternative to /tmp. Here's a scenario: A user sets up two firejails for two apps. One jailed app given read-only access to sensitive data but is cut off from all network access. The other is given network access but is cut off from reading sensitive data. Those two apps can communicate through the /run/user/1000/pulse dir, for instance, and tunnel the sensitive data out to the network. Perhaps there should be a --private-run option?
gitea-mirror 2026-05-05 08:39:33 -06:00
Author
Owner

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

As /run/user/$UID is the only user-writable place below /run usually, you can solve this as follows since 0.9.60

whitelist ${RUNUSER}/bus
whitelist ${RUNUSER}/gnupg
whitelist ${RUNUSER}/pulse
read-only ${RUNUSER}/gnupg
read-only ${RUNUSER}/pulse

Assuming that /run/shm, if it exists, is not a directory but a symbolic link to /dev/shm (which is the most common setup).

<!-- gh-comment-id:579211348 --> @smitsohu commented on GitHub (Jan 28, 2020): As `/run/user/$UID` is the only user-writable place below `/run` usually, you can solve this as follows since 0.9.60 ``` whitelist ${RUNUSER}/bus whitelist ${RUNUSER}/gnupg whitelist ${RUNUSER}/pulse read-only ${RUNUSER}/gnupg read-only ${RUNUSER}/pulse ``` Assuming that `/run/shm`, if it exists, is not a directory but a symbolic link to `/dev/shm` (which is the most common setup).
Author
Owner

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

Perhaps there should be a --private-run option?

Good question! Over time there is likely going to be whitelist support for /run, so we could have a whitelist-run-common.inc at some point, similar to what we are doing now in whitelist-var-common.inc or whitelist-usr-share-common.inc.

<!-- gh-comment-id:579291134 --> @smitsohu commented on GitHub (Jan 28, 2020): > Perhaps there should be a --private-run option? Good question! Over time there is likely going to be whitelist support for /run, so we could have a whitelist-run-common.inc at some point, similar to what we are doing now in whitelist-var-common.inc or whitelist-usr-share-common.inc.
Author
Owner

@rusty-snake commented on GitHub (Jan 28, 2020):

As /run/user/$UID is the only user-writable place below /run usually, you can solve this as follows since 0.9.60

whitelist ${RUNUSER}/bus
whitelist ${RUNUSER}/gnupg
whitelist ${RUNUSER}/pulse
read-only ${RUNUSER}/gnupg
read-only ${RUNUSER}/pulse

For Wayland: whitelist ${RUNUSER}/wayland-?

<!-- gh-comment-id:579301889 --> @rusty-snake commented on GitHub (Jan 28, 2020): > As `/run/user/$UID` is the only user-writable place below `/run` usually, you can solve this as follows since 0.9.60 > > ``` > whitelist ${RUNUSER}/bus > whitelist ${RUNUSER}/gnupg > whitelist ${RUNUSER}/pulse > read-only ${RUNUSER}/gnupg > read-only ${RUNUSER}/pulse > ``` For Wayland: `whitelist ${RUNUSER}/wayland-?`
Author
Owner

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

As /run/user/$UID is the only user-writable place below /run usually, you can solve this as follows since 0.9.60

We have also /run/lock, but Firejail mounts a tmpfs on it as long as there is a symbolic link /var/lock -> /run/lock

<!-- gh-comment-id:579340840 --> @smitsohu commented on GitHub (Jan 28, 2020): > As /run/user/$UID is the only user-writable place below /run usually, you can solve this as follows since 0.9.60 We have also /run/lock, but Firejail mounts a tmpfs on it as long as there is a symbolic link /var/lock -> /run/lock
Author
Owner

@jonleivent commented on GitHub (Jan 28, 2020):

Thanks for the help! I also found that it was possible to blacklist many of the items within /run and still run many useful apps.

Another suggestion: --audit should try to find writable spots such as those discussed under /run. Also readable spots not under /home that are writable by non-root outside the jail.

Is --audit user extensible? I could write my own auditor, but suspect that audit has tools within it that would make things easier.

<!-- gh-comment-id:579421380 --> @jonleivent commented on GitHub (Jan 28, 2020): Thanks for the help! I also found that it was possible to blacklist many of the items within /run and still run many useful apps. Another suggestion: --audit should try to find writable spots such as those discussed under /run. Also readable spots not under /home that are writable by non-root outside the jail. Is --audit user extensible? I could write my own auditor, but suspect that audit has tools within it that would make things easier.
Author
Owner

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

Also readable spots not under /home that are writable by non-root outside the jail.

That part is going to be difficult. faudit is just a little separate program that is executed inside the sandbox and reports what it can and what it can't see, without any knowledge of the world outside the jail.

Is --audit user extensible? I could write my own auditor, but suspect that audit has tools within it that would make things easier.

No, currently it is not user extensible.

<!-- gh-comment-id:579451433 --> @smitsohu commented on GitHub (Jan 28, 2020): > Also readable spots not under /home that are writable by non-root outside the jail. That part is going to be difficult. faudit is just a little separate program that is executed inside the sandbox and reports what it can and what it can't see, without any knowledge of the world outside the jail. > Is --audit user extensible? I could write my own auditor, but suspect that audit has tools within it that would make things easier. No, currently it is not user extensible.
Author
Owner

@jonleivent commented on GitHub (Jan 29, 2020):

That part is going to be difficult.

How about this idea: outside of the jail, generate a full list of [user writable paths, inodes] not in /home, save it in a place where the jail can read it, and enter the jail (or do a --put to get it there). Inside the jail, for each path in that list, see of the path's inode is the same as on the list, and if so say if the path is readable or writable.

That of course covers inodes existing at that time, not what may exist later. But, it is a start.

<!-- gh-comment-id:579531123 --> @jonleivent commented on GitHub (Jan 29, 2020): > That part is going to be difficult. How about this idea: outside of the jail, generate a full list of [user writable paths, inodes] not in /home, save it in a place where the jail can read it, and enter the jail (or do a --put to get it there). Inside the jail, for each path in that list, see of the path's inode is the same as on the list, and if so say if the path is readable or writable. That of course covers inodes existing at that time, not what may exist later. But, it is a start.
Author
Owner

@jonleivent commented on GitHub (Jan 29, 2020):

Wasn't difficult at all, and works well. It found some other holes, for instance things in /var/spool. I will blacklist /var/spool. The only false positives were in /dev/pts, and I have --private-dev. But I guess that's the special way that /dev/pts works - with inodes that don't really reflect identity.

Command on the outside of the jail is:

find / \( -path ~ -prune \) -o -type l -o \( -writable -ls \) 2>/dev/null | awk '{print $1 " " $NF}' > /tmp/writable-inodes.txt

Then --put /tmp/writable-inodes.txt into the jail at /tmp/writable-inodes.txt and run this in the jail:

while read -r i p; do
    if j=$(stat --format='%i' $p 2>/dev/null) && [ $i -eq $j ]; then
        find $p -maxdepth 0 -writable -printf '%h/%f is writable\n'
        find $p -maxdepth 0 -readable -printf '%h/%f is readable\n'
    fi
done < /tmp/writable-inodes.txt

I know using find -maxdepth 0 in the above to test -writable and -readable is a bit unusual, but I wanted to stay consistent to the find usage outside.

<!-- gh-comment-id:579577113 --> @jonleivent commented on GitHub (Jan 29, 2020): Wasn't difficult at all, and works well. It found some other holes, for instance things in /var/spool. I will blacklist /var/spool. The only false positives were in /dev/pts, and I have --private-dev. But I guess that's the special way that /dev/pts works - with inodes that don't really reflect identity. Command on the outside of the jail is: ``` find / \( -path ~ -prune \) -o -type l -o \( -writable -ls \) 2>/dev/null | awk '{print $1 " " $NF}' > /tmp/writable-inodes.txt ``` Then --put /tmp/writable-inodes.txt into the jail at /tmp/writable-inodes.txt and run this in the jail: ``` while read -r i p; do if j=$(stat --format='%i' $p 2>/dev/null) && [ $i -eq $j ]; then find $p -maxdepth 0 -writable -printf '%h/%f is writable\n' find $p -maxdepth 0 -readable -printf '%h/%f is readable\n' fi done < /tmp/writable-inodes.txt ``` I know using find -maxdepth 0 in the above to test -writable and -readable is a bit unusual, but I wanted to stay consistent to the find usage outside.
Author
Owner

@Vincent43 commented on GitHub (Feb 4, 2020):

For Wayland: whitelist ${RUNUSER}/wayland-?

@rusty-snake hm, for me neither of wayland-? or wayland-* or wayland* seems to work, only exact wayland-0 match does.

<!-- gh-comment-id:581871228 --> @Vincent43 commented on GitHub (Feb 4, 2020): > For Wayland: whitelist ${RUNUSER}/wayland-? @rusty-snake hm, for me neither of `wayland-?` or `wayland-*` or `wayland*` seems to work, only exact `wayland-0` match does.
Author
Owner

@Vincent43 commented on GitHub (Feb 4, 2020):

Ah, you know a9c6f9f423 😄

<!-- gh-comment-id:582002193 --> @Vincent43 commented on GitHub (Feb 4, 2020): Ah, you know https://github.com/netblue30/firejail/commit/a9c6f9f42346a067343f72906ca8016097bee8b1 😄
Author
Owner

@rusty-snake commented on GitHub (May 18, 2021):

You can now use whitelist /run/foo (ed7db09) and wrc PR is on the way.

<!-- gh-comment-id:843207471 --> @rusty-snake commented on GitHub (May 18, 2021): You can now use `whitelist /run/foo` (ed7db09) and wrc PR is on the way.
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#1994
No description provided.