|
|
|
@ -225,16 +225,45 @@ mergerfs is a multithreaded application in order to handle requests |
|
|
|
from the kernel concurrently. Each FUSE message has a header with |
|
|
|
certain details about the request including the process ID (pid) of |
|
|
|
the requesting application, the process' effective user id (uid), and |
|
|
|
group id (gid). To ensure proper POSIX filesystem behavior and |
|
|
|
security mergerfs must change its identity to match that of the |
|
|
|
requester when performing the certain functions on the underlying |
|
|
|
filesystem. As required by standards most Unix/POSIX based systems a |
|
|
|
process and all its threads are under the same uid and gid. However, |
|
|
|
on Linux each thread **may** have its own credentials. This allows |
|
|
|
mergerfs to be multithreaded and for each thread to change to the |
|
|
|
credentials as required by the incoming message it is |
|
|
|
handling. However, currently on FreeBSD this is not possible (though |
|
|
|
there has been |
|
|
|
group id (gid). |
|
|
|
|
|
|
|
FUSE and the kernel have two ways of managing |
|
|
|
permissions. `default_permissions` and not. When default permissions |
|
|
|
is enabled the kernel will do the entitlement checks and only allow |
|
|
|
requests through which have been allowed. When not enabled it is the |
|
|
|
responsibility of the FUSE server, in this case mergerfs, to do that. |
|
|
|
|
|
|
|
Prior to mergerfs v2.42.0 it would enable `default_permissions` but |
|
|
|
also leveraged the uid and gid available in each FUSE request. The |
|
|
|
thread actioning the request would change its credentials to match |
|
|
|
those of the requesting application to ensure permissions were |
|
|
|
properly handled as well as dealing with some quirks of non-POSIX |
|
|
|
compatible filesystems. However, this strategy had two major |
|
|
|
issues. First, it was not compatible with the new `allow-idmap` |
|
|
|
feature of FUSE which allows a filesystem to advertise it can be used |
|
|
|
with id mapping which is often used with containers. Secondly, it |
|
|
|
caused permission issues when the kernel would say something was |
|
|
|
allowed but due to the way mergerfs was changing creds would |
|
|
|
fail. This mostly came in the form of `chroot`ed setups like used in |
|
|
|
containers. Neither of these tended to impact casual users but did |
|
|
|
break some niche or power user use cases. Since the casual user won't |
|
|
|
notice the subtle changes and it would enable new use cases it was |
|
|
|
decided that the credential handling would change. |
|
|
|
|
|
|
|
As of v2.42.0 mergerfs now runs effectively as root when performing |
|
|
|
more filesystem calls. On Linux it uses `capabilities` which allow any |
|
|
|
user it changes to to act as if it were root. This minimizes the |
|
|
|
amount of credential changing. When creating new files, directories, |
|
|
|
symlinks, etc. it will change the thread's creds to the requester |
|
|
|
uid:gid to ensure the file is created as the user atomically. |
|
|
|
|
|
|
|
On FreeBSD the situation is more complicated. As required by standards |
|
|
|
most Unix/POSIX based systems a process and all its threads are under |
|
|
|
the same uid and gid. However, on Linux each thread **may** have its |
|
|
|
own credentials. This allows mergerfs to be multithreaded and for each |
|
|
|
thread to change to the credentials as required by the incoming |
|
|
|
message it is handling. However, currently on FreeBSD this is not |
|
|
|
possible (though there has been |
|
|
|
[discussions](https://wiki.freebsd.org/Per-Thread%20Credentials)) and |
|
|
|
as such must change the credentials of the whole application when |
|
|
|
actioning messages. mergerfs does optimize this behavior by only |
|
|
|
|