03 Nov, 2020
5 commits
-
When using FUSE passthrough, read/write operations are directly forwarded
to the lower file system file through VFS, but there is no guarantee that
the process that is triggering the request has the right permissions to
access the lower file system. This would cause the read/write access to
fail.In passthrough file systems, where the FUSE daemon is responsible for the
enforcement of the lower file system access policies, often happens that
the process dealing with the FUSE file system doesn't have access to the
lower file system.
Being the FUSE daemon in charge of implementing the FUSE file operations,
that in the case of read/write operations usually simply results in the
copy of memory buffers from/to the lower file system respectively, these
operations are executed with the FUSE daemon privileges.This patch adds a reference to the FUSE daemon credentials, referenced at
FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl() time so that they can be used to
temporarily raise the user credentials when accessing lower file system
files in passthrough.
The process accessing the FUSE file with passthrough enabled temporarily
receives the privileges of the FUSE daemon while performing read/write
operations. Similar behavior is implemented in overlayfs.
These privileges will be reverted as soon as the IO operation completes.
This feature does not provide any higher security privileges to those
processes accessing the FUSE file system with passthrough enabled. This is
because it is still the FUSE daemon responsible for enabling or not the
passthrough feature at file open time, and should enable the feature only
after appropriate access policy checks.Bug: 168023149
Link: https://lore.kernel.org/lkml/20201026125016.1905945-6-balsini@android.com/
Signed-off-by: Alessio Balsini
Signed-off-by: Alessio Balsini
Change-Id: I1123f8113578eb8713f2b777a1b5ec76882bd762 -
Extend the passthrough feature by handling asynchronous IO both for read
and write operations.When an AIO request is received, if the request targets a FUSE file with
the passthrough functionality enabled, a new identical AIO request is
created. The new request targets the lower file system file and gets
assigned a special FUSE passthrough AIO completion callback.
When the lower file system AIO request is completed, the FUSE passthrough
AIO completion callback is executed and propagates the completion signal to
the FUSE AIO request by triggering its completion callback as well.Bug: 168023149
Link: https://lore.kernel.org/lkml/20201026125016.1905945-5-balsini@android.com/
Signed-off-by: Alessio Balsini
Signed-off-by: Alessio Balsini
Change-Id: I1e6b4602e0813c425a41f370c856d2e99e771277 -
All the read and write operations performed on fuse_files which have the
passthrough feature enabled are forwarded to the associated lower file
system file via VFS.Sending the request directly to the lower file system avoids the userspace
round-trip that, because of possible context switches and additional
operations might reduce the overall performance, especially in those cases
where caching doesn't help, for example in reads at random offsets.Verifying if a fuse_file has a lower file system file associated with can
be done by checking the validity of its passthrough_filp pointer. This
pointer is not NULL only if passthrough has been successfully enabled via
the appropriate ioctl().
When a read/write operation is requested for a FUSE file with passthrough
enabled, a new equivalent VFS request is generated, which instead targets
the lower file system file.
The VFS layer performs additional checks that allow for safer operations
but may cause the operation to fail if the process accessing the FUSE file
system does not have access to the lower file system.This change only implements synchronous requests in passthrough, returning
an error in the case of asynchronous operations, yet covering the majority
of the use cases.Bug: 168023149
Link: https://lore.kernel.org/lkml/20201026125016.1905945-4-balsini@android.com/
Signed-off-by: Alessio Balsini
Signed-off-by: Alessio Balsini
Change-Id: If76bb8725e1ac567f9dbe3edb79ebb4d43d77dfb -
Implement the FUSE passthrough ioctl() that associates the lower
(passthrough) file system file with the fuse_file.The file descriptor passed to the ioctl() by the FUSE daemon is used to
access the relative file pointer, that will be copied to the fuse_file data
structure to consolidate the link between the FUSE and lower file system.To enable the passthrough mode, userspace triggers the
FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl() and, if the call succeeds,
receives back an identifier that will be used at open/create response
time in the fuse_open_out field to associate the FUSE file to the lower
file system file.
The value returned by the ioctl() to userspace can be:
- > 0: success, the identifier can be used as part of an open/create
reply.
- < 0: an error occurred.
The value 0 has been left unused for backward compatibility: the
fuse_open_out field that is used to pass the passthrough_fh back to the
kernel uses the same bits that were previously as struct padding,
zero-initialized in the common libfuse implementation. Removing the 0
value fixes the ambiguity between the case in which 0 corresponds to a
real passthrough_fh or a missing implementation, simplifying the
userspace implementation.For the passthrough mode to be successfully activated, the lower file
system file must implement both read_ and write_iter file operations.
This extra check avoids special pseudo files to be targeted for this
feature.
Passthrough comes with another limitation: no further file system stacking
is allowed for those FUSE file systems using passthrough.Bug: 168023149
Link: https://lore.kernel.org/lkml/20201026125016.1905945-3-balsini@android.com/
Signed-off-by: Alessio Balsini
Signed-off-by: Alessio Balsini
Change-Id: Id6067dcb882d58daef5ffe44355c383cabeed547 -
Expose the FUSE_PASSTHROUGH interface to userspace and declare all the
basic data structures and functions as the skeleton on top of which the
FUSE passthrough functionality will be built.As part of this, introduce the new FUSE passthrough ioctl(), which
allows
the FUSE daemon to specify a direct connection between a FUSE file and a
lower file system file. Such ioctl() requires userspace to pass the file
descriptor of one of its opened files through the fuse_passthrough_out
data
structure introduced in this patch. This structure includes extra fields
for possible future extensions.
Also, add the passthrough functions for the set-up and tear-down of the
data structures and locks that will be used both when fuse_conns and
fuse_files are created/deleted.Bug: 168023149
Link: https://lore.kernel.org/lkml/20201026125016.1905945-2-balsini@android.com/
Signed-off-by: Alessio Balsini
Signed-off-by: Alessio Balsini
Change-Id: I6dd150b93607e10ed53f7e7975b35b6090080fa2