Does Landlock not work with eCryptfs?
Mickaël Salaün
mic at digikod.net
Tue Mar 21 16:36:19 UTC 2023
There is an inconsistency between ecryptfs_dir_open() and
ecryptfs_open(). ecryptfs_dir_open() actually checks access right to the
lower directory, which is why landlocked processes may not access the
upper directory when reading its content. ecryptfs_open() uses a cache
for upper files (which could be a problem on its own). The execution
flow is:
ecryptfs_open() -> ecryptfs_get_lower_file() ->
ecryptfs_init_lower_file() -> ecryptfs_privileged_open()
In ecryptfs_privileged_open(), the dentry_open() call failed if access
to the lower file is not allowed by Landlock (or other access-control
systems). Then wait_for_completion(&req.done) waits for a kernel's
thread executing ecryptfs_threadfn(), which uses the kernel's credential
to access the lower file.
I think there are two main solutions to fix this consistency issue:
- store the mounter credentials and uses them instead of the kernel's
credentials for lower file and directory access checks
(ecryptfs_dir_open and ecryptfs_threadfn changes);
- use the kernel's credentials for all lower file/dir access check,
especially in ecryptfs_dir_open().
I think using the mounter credentials makes more sense, is much safer,
and fits with overlayfs. It may not work in cases where the mounter
doesn't have access to the lower file hierarchy though.
File creation calls vfs_*() helpers (lower directory) and there is not
path nor file security hook calls for those, so it works unconditionally.
From Landlock end users point of view, it makes more sense to grants
access to a file hierarchy (where access is already allowed) and be
allowed to access this file hierarchy, whatever it belongs to a specific
filesystem (and whatever the potential lower file hierarchy, which may
be unknown to users). This is how it works for overlayfs and I'd like to
have the same behavior for ecryptfs.
On 20/03/2023 18:21, Mickaël Salaün wrote:
>
> On 20/03/2023 18:15, Günther Noack wrote:
>> Hello!
>>
>> On Sun, Mar 19, 2023 at 10:00:46PM +0100, Mickaël Salaün wrote:
>>> Hi Günther,
>>>
>>> Thanks for the report, I confirm there is indeed a bug. I tested with a
>>> Debian distro:
>>>
>>> ecryptfs-setup-private --nopwcheck --noautomount
>>> ecryptfs-mount-private
>>> # And then with the kernel's sample/landlock/sandboxer:
>>> LL_FS_RO="/usr" LL_FS_RW="${HOME}/Private" sandboxer ls ~/Private
>>> ls: cannot open directory '/home/user/Private': Permission denied
>>>
>>> Actions other than listing a directory (e.g. creating files/directories,
>>> reading/writing to files) are controlled as expected. The issue might be
>>> that directories' inodes are not the same when listing the content of a
>>> directory or when creating new files/directories (which is weird). My
>>> hypothesis is that Landlock would then deny directory reading because the
>>> directory's inode doesn't match any rule. It might be related to the overlay
>>> nature of ecryptfs.
>>>
>>> Tyler, do you have some idea?
>>
>> I had a hunch, and found out that the example can be made to work by
>> granting the LANDLOCK_ACCESS_FS_READ_DIR right on the place where the
>> *encrypted* version of that home directory lives:
>>
>> err := landlock.V1.RestrictPaths(
>> landlock.RODirs(dir),
>> landlock.PathAccess(llsys.AccessFSReadDir, "/home/.ecryptfs/gnoack/.Private"),
>> )
>>
>> It does seem a bit like eCryptfs it calling security_file_open() under
>> the hood for the encrypted version of that file? Is that correct?
>
> Yes, that's right, the lower directory is used to list the content of
> the ecryptfs directory:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ecryptfs/file.c#n112
> iterate_dir(lower_file, …)
More information about the Linux-security-module-archive
mailing list