mullvad / mullvadvpn-app

The Mullvad VPN client app for desktop and mobile
https://mullvad.net/
GNU General Public License v3.0
4.99k stars 335 forks source link

SELinux issues with daemon on ostree-based Fedora distributions #1570

Closed nlordell closed 1 year ago

nlordell commented 4 years ago

I imagine there are not very many Fedora Silverblue users so it would be totally understandable if this issue had a very low priority. I just though I would report it in case someone else ran into the same issue as I did and wanted to share my findings.

So in ostree-based Fedora, specifically Fedora Silverblue, it looks like RPMs that install to /opt get installed to /lib/usr/opt instead. From what I understand, this is because RPMs must be installed to parts of the file system that are immutable, and /opt is not. This causes problems with everything that points to /opt/Mullvad VPN installation directory (such as the systemd service, the post install script, the .desktop file, etc.).

A quick work-around (use at your own peril) is to create a symbolic link in /opt to the RPM installation location.

sudo ln -s "/usr/lib/opt/Mullvad VPN" "/opt/Mullvad VPN"

This still doesn't 100% work, if I were then to enable the mullvad-daemon service:

sudo systemctl enable "/opt/Mullvad VPN/resources/mullvad-daemon.service"

then the service fails to start because (of what I can gather - I plan on investigating a bit more future) of some SELinux policy that prevents it from creating files in /var/log/mullvad-vpn. Specifically, the line that errors is: https://github.com/mullvad/mullvadvpn-app/blob/8b24d7dc78a77a264b60f7f3d36fbfbd28e5e52d/talpid-core/src/logging/mod.rs#L28

The logs:

Mar 14 23:52:54 my-pc systemd[1]: Started Mullvad VPN daemon.
Mar 14 23:52:54 my-pc mullvad-daemon[10927]: Error: Unable to initialize logger
Mar 14 23:52:54 my-pc mullvad-daemon[10927]: Caused by: Unable to rotate daemon log file
Mar 14 23:52:54 my-pc mullvad-daemon[10927]: Caused by: Unable to create new log file
Mar 14 23:52:54 my-pc mullvad-daemon[10927]: Caused by: Permission denied (os error 13)
Mar 14 23:52:54 my-pc systemd[1]: mullvad-daemon.service: Main process exited, code=exited, status=1/FAILURE
Mar 14 23:52:54 my-pc systemd[1]: mullvad-daemon.service: Failed with result 'exit-code'.

You can however, just run the daemon manually as root:

sudo "/opt/Mullvad VPN/resources/mullvad-daemon"

which starts the daemon successfully and works with both the GUI and the CLI.

faern commented 4 years ago

Thanks for reporting this. You are right that we probably can't prioritize this high at the moment.

Where would one write system service logs on Silverblue then? /var/log is a pretty standard directory :O

nlordell commented 4 years ago

Where would one write system service logs on Silverblue then? /var/log is a pretty standard directory :O

The directory is right, in fact other services log to there as well. I think its some weird SE Linux thing going on that I don't understand. I'll try to make some time to figure out exactly why and report back if and when I do.

nlordell commented 4 years ago

So the startup error from creating the log file is definitely an SELinux problem, looking at the audit logs:

type=AVC msg=audit(1584817968.440:246): avc:  denied  { create } for  pid=7414 comm="mullvad-daemon" name="daemon.log" scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=file permissive=0

Unfortunately my SELinux understanding is very poor.

nlordell commented 4 years ago

Woohoo :tada: So I got it working, it looks like its was a combination of things.

The first issue, and also the easiest to work around, is the fact that the RPM installs to /opt, which Silverblue doesn't like because of how it does immutable filesystems. rpm-ostree will install Mullvad VPN directory to /usr/lib/opt instead. Now, it looks like rpm-ostree is trying to create a symlink from /opt/Mullvad VPN -> /usr/lib/opt/Mullvad VPN but failing because of the space. I created an issue coreos/rpm-ostree#2029, but it has not been acknowledged yet, so I might have just misunderstood what was going on. Either way, this is fairly simple to work around and just requires creating a symbolic link in /opt! :confetti_ball:

The second issue, and by far the more complicated of the two, was the SELinux stuff (which, disclaimer, I understand almost nothing about). The issue here was that the mullvad binaries are all labeled with some lib_t type by default, and that does not have write permissions to the required runtime directories (/var/{cache,log} and /etc) nor permit interacting with networking bits it needs. One major difference between Silverblue and standard Fedora Workstation (where the daemon runs without a problem) is that files installed under /opt should get the usr_t type. While this SELinux rule exists in Silverblue as well, the fact that /opt gets mapped to /usr/lib/opt makes it use a different label lib_t instead. The latter seams to have reduced permissions compared to the usr_t label that installation usually has when on standard workstation and was the source of the permission issues. This can be fixed by adding a file context entry so that files installed under Mullvad VPN directory have the usr_t type instead of the more restrictive lib_t type. I believe this is a bug in the default SELinux policy in Silverblue and created an issue here: https://pagure.io/teamsilverblue/issue/80.

:warning: DISCLAIMER :warning:: The following workaround worked for me, but I do not know enough about SELinux to be able to say what I'm doing is safe or the correct way to do things:

First, set everything up - note this should be done before installing the RPM.

ln -s '/usr/lib/opt/Mullvad VPN' '/opt/Mullvad VPN'
semanage fcontext -a -t usr_t '/usr/lib/opt/Mullvad.VPN(/.*)?'

(Note the Mullvad.VPN instead of Mullvad VPN, this is because I coudn't figure out how to get semanage to work with paths with spaces, but since it uses regexp, the . works :man_facepalming:)

Now install the RPM:

rpm-ostree install MullvadVPN.*.rpm
systemctl reboot

Now, I'm not sure why this needs to be done manually, but the systemd services were not properly setup after install. I looked at other RPMs and they use %systemd_* entries in the spec instead of doing it with an install scripts. It could have something to do with this, but I didn't dig deeper.

systemctl enable '/opt/Mullvad VPN/resources/mullvad-daemon.service'
systemctl start mullvad-daemon.service

Voila! :man_dancing:.

I think, both issues are actually rpm-ostree and SELinux policy bugs and not actually issues with the Mullvad RPM package so this issue can be closed. It would be nice to keep this information around somewhere in case someone else runs into this issue.

faern commented 4 years ago

Great research. Hopefully this can be of good use for other Silverblue users.

The issue can stay open for now. It's still true that this app does not work on ostree based Fedora distros.

faern commented 4 years ago

This is already fixed according to https://github.com/mullvad/mullvadvpn-app/issues/1861#issuecomment-648105759. Please reopen if this is still a problem.

nlordell commented 4 years ago

Please reopen if this is still a problem.

Sorry maybe my comment wasn't super clear :disappointed:. The issue with /opt/Mullvad VPN not being available after install is fixed, however the SELinux issues are still a problem causing mullvad-daemon to fail at startup as a systemd service.

TommyTran732 commented 3 years ago

Please reopen if this is still a problem.

Sorry maybe my comment wasn't super clear . The issue with /opt/Mullvad VPN not being available after install is fixed, however the SELinux issues are still a problem causing mullvad-daemon to fail at startup as a systemd service.

Apparently this is caused by the symlink from /opt/Mullvad VPN/mullvad-daemon.service to /etc/systemd/system/mullvad-daemon.service. I tried to look it up and it could be because the order in which everything to mounted or something, but I don't have a nice solution for this :/

The only work around for this is to delete the symlink /etc/systemd/system/mullvad-daemon.service and copying /opt/Mullvad VPN/mullvad-daemon.service over. After that you can do systemctl enable --now mullvad-daemon and it should work properly.

TommyTran732 commented 3 years ago

Update: This issue also exists on OpenSUSE MicroOS.

vorot93 commented 3 years ago

@faern any progress on this?

faern commented 3 years ago

Not really. ostree based distributions are not currently supported and we don't have the bandwidth to start supporting them right now. PRs for solving this would be accepted if they are nice and clean and don't mess up for distributions we actually do support.

SaladinAyyub commented 2 years ago

I have written a sh file to achieve this thanks to the research of @nlordell . Once I confirm everything is working as expected I will share it.

Ramblurr commented 2 years ago

@shuriken1812 mind sharing your script?

I've managed to install the rpm and seet the selinux context on the /opt/Mullvad VPN directory, but the daemon fails to start:

[2022-05-23 10:00:39.998][mullvad_daemon::version][INFO] Starting mullvad-daemon - 2022.1 2022-03-01
[2022-05-23 10:00:39.998][mullvad_daemon][INFO] Logging to /var/log/mullvad-vpn
[2022-05-23 10:00:39.999][mullvad_daemon::rpc_uniqueness_check][DEBUG] Failed to locate/connect to another daemon instance, assuming there isn't one
[2022-05-23 10:00:39.999][mullvad_daemon][INFO] Management interface listening on /var/run/mullvad-vpn
[2022-05-23 10:00:39.999][mullvad_daemon::settings][INFO] Loading settings from /etc/mullvad-vpn/settings.json
[2022-05-23 10:00:39.999][mullvad_daemon::target_state][ERROR] Error: Failed to write cache target state
Caused by: Permission denied (os error 13)
[2022-05-23 10:00:39.999][mullvad_rpc::address_cache][DEBUG] Loading API addresses from /var/cache/mullvad-vpn/api-ip-address.txt
[2022-05-23 10:00:39.999][mullvad_rpc::address_cache][DEBUG] Loading API addresses from /usr/lib/opt/Mullvad VPN/resources/api-ip-address.txt
[2022-05-23 10:00:39.999][mullvad_rpc::address_cache][DEBUG] Using API address: 193.138.218.78:443
[2022-05-23 10:00:39.999][mullvad_daemon::target_state][ERROR] Error: Cannot delete target tunnel state cache
Caused by: No such file or directory (os error 2)
[2022-05-23 10:00:39.999][mullvad_daemon][ERROR] Error: Unable to initialize daemon
Caused by: Unable to create RPC client
Caused by: Failed to load address cache
Caused by: Failed to update the address cache file
Caused by: Permission denied (os error 13)
[2022-05-23 10:00:39.999][mullvad_daemon][DEBUG] Process exiting with code 1

selinux shows this denial when starting the service:

$ sudo ausearch -m AVC,USER_AVC -ts recent
time->Mon May 23 10:02:30 2022
type=AVC msg=audit(1653292950.764:670): avc:  denied  { create } for  pid=5877 comm="tokio-runtime-w" name="api-cache.temp" scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file permissive=0
Ramblurr commented 2 years ago

This is happening because the mullvad-daemon is trying to write the api cache file, I assume in the current working directory of the daemon, which selinux doesn't allow.

Since silverblue has an immutable fs, I can't use chcon to change the selinux label of the daemon binary.

1player commented 2 years ago

I've made a script to start and stop Mullvad from its Wireguard config files (with bonus support for the Tailscale VPN): https://gist.github.com/1player/e9cadfef833d5eb5a23c30223f560147

Requires the wireguard-tools package on Fedora, works great here on Silverblue.

pinkisemils commented 2 years ago

This is happening because the mullvad-daemon is trying to write the api cache file, I assume in the current working directory of the daemon, which selinux doesn't allow.

Since silverblue has an immutable fs, I can't use chcon to change the selinux label of the daemon binary.

You can set the path of the cache directory via an environment variable.

alastortenebris commented 2 years ago

As of version 2022.5 with Fedora Kinoite 36, I was able to install Mullvad and connect with only a few extra steps.

The steps I did:

  1. Install the RPM
  2. Run sudo systemctl enable --now mullvad-daemon
  3. Run sudo rpm-ostree install libappindicator-gtk3 as it is not installed by default on Kinoite.
  4. Reboot. Live applying will not work.

My guess is that now that the Mullvad binaries and services are not symlinked, they work.

OSLDNKKfEUVTABDLiNgk commented 1 year ago

As of version 2022.5 with Fedora Kinoite 36, I was able to install Mullvad and connect with only a few extra steps.

The steps I did:

1. Install the RPM

2. Run `sudo systemctl enable --now mullvad-daemon`

3. Run `sudo rpm-ostree install libappindicator-gtk3` as it is not installed by default on Kinoite.

4. Reboot. Live applying will not work.

My guess is that now that the Mullvad binaries and services are not symlinked, they work.

Silverblue users only need these three steps:

  1. Install the RPM
  2. Reboot
  3. Run sudo systemctl enable --now mullvad-daemon in Terminal
alistair23 commented 1 year ago

The issue does seem to be fixed. 2022.5 now works great on Kinoite

abuturabofficial commented 1 year ago

As of version 2022.5 with Fedora Kinoite 36, I was able to install Mullvad and connect with only a few extra steps. The steps I did:

1. Install the RPM

2. Run `sudo systemctl enable --now mullvad-daemon`

3. Run `sudo rpm-ostree install libappindicator-gtk3` as it is not installed by default on Kinoite.

4. Reboot. Live applying will not work.

My guess is that now that the Mullvad binaries and services are not symlinked, they work.

Silverblue users only need these three steps:

  1. Install the RPM
  2. Reboot
  3. Run sudo systemctl enable --now mullvad-daemon in Terminal

I can confirm as of DEC 2022, it works as it should on SilverBlue.

faern commented 1 year ago

I'm closing this as there are reports of it being fixed. Please reopen/ping me if it's still an issue.