snaps don't start when current working directory is on a remote FS (sshfs, NFS)
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
snapd |
Triaged
|
Wishlist
|
Unassigned | ||
firefox (Ubuntu) |
Confirmed
|
Undecided
|
Unassigned | ||
thunderbird (Ubuntu) |
Confirmed
|
Undecided
|
Unassigned |
Bug Description
All snaps fail to start when the current working directory is under a sshfs tree:
/tmp/test$ hello-world
cannot open path of the current working directory: Permission denied
The reason is that sshfs by default disallows the root user (or any user other than the one who created the mount) from accessing the mounted file system, and snap-confine is a setuid program which before dropping its privileges tries to open the current working directory and terminates if that operation fails:
In sc_preserve_
proc_state-
openat(
O_PATH | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
if (proc_state-
die("cannot open path of the current working directory");
}
There are workarounds for this situations: one can add the "user_allow_other" option to /etc/fuse.conf and call sshfs with the "-o allow_root" option, and this will allow snaps to start, yet it's a suboptimal experience.
Possible solutions:
A) Move this part of code a bit later, after having dropping the privileges.
B) Drop the privileges before making this call, and restore them afterwards.
C) Use get_current_
description: | updated |
Changed in snapd: | |
status: | New → Triaged |
summary: |
- snaps dont't start when current working directory is on sshfs + snaps don't start when current working directory is on sshfs |
summary: |
- snaps don't start when current working directory is on sshfs + snaps don't start when current working directory is on a remote FS + (sshfs, NFS) |
Update: none of the solutiones mentioned above work, unfortunately.
The problem is that the FUSE kernel module not only checks the effective user ID, but also the real and saved one:
https:/ /github. com/torvalds/ linux/blob/ 2bf06b8e6428025 1775011f63d44e7 bfc48dbdfd/ fs/fuse/ dir.c#L1223- L1240
As a privileged process, we can set all of the user and group IDs to arbitrary values, and can therefore pass this FUSE check; but once we do, there's no way to get back to being a privileged process, and therefore this is one of the last operations snap-confine performs before executing the desired program.
One option that we might want to investigate is setting all the needed capabilities on our process at startup (while we are still root), set the SECBIT_KEEP_CAPS bit, and then drop all our user IDs to the user ones. As long as we have all the capabilities set, we should be able to perform all the operations we need to; and then capabilities would be normally lost when we call execve().