| From d9818b3e906a0ee1ab02ea79e74a2f755fc5461a Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net> |
| Date: Mon, 19 Feb 2024 20:03:45 +0100 |
| Subject: landlock: Fix asymmetric private inodes referring |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Mickaël Salaün <mic@digikod.net> |
| |
| commit d9818b3e906a0ee1ab02ea79e74a2f755fc5461a upstream. |
| |
| When linking or renaming a file, if only one of the source or |
| destination directory is backed by an S_PRIVATE inode, then the related |
| set of layer masks would be used as uninitialized by |
| is_access_to_paths_allowed(). This would result to indeterministic |
| access for one side instead of always being allowed. |
| |
| This bug could only be triggered with a mounted filesystem containing |
| both S_PRIVATE and !S_PRIVATE inodes, which doesn't seem possible. |
| |
| The collect_domain_accesses() calls return early if |
| is_nouser_or_private() returns false, which means that the directory's |
| superblock has SB_NOUSER or its inode has S_PRIVATE. Because rename or |
| link actions are only allowed on the same mounted filesystem, the |
| superblock is always the same for both source and destination |
| directories. However, it might be possible in theory to have an |
| S_PRIVATE parent source inode with an !S_PRIVATE parent destination |
| inode, or vice versa. |
| |
| To make sure this case is not an issue, explicitly initialized both set |
| of layer masks to 0, which means to allow all actions on the related |
| side. If at least on side has !S_PRIVATE, then |
| collect_domain_accesses() and is_access_to_paths_allowed() check for the |
| required access rights. |
| |
| Cc: Arnd Bergmann <arnd@arndb.de> |
| Cc: Christian Brauner <brauner@kernel.org> |
| Cc: Günther Noack <gnoack@google.com> |
| Cc: Jann Horn <jannh@google.com> |
| Cc: Shervin Oloumi <enlightened@chromium.org> |
| Cc: stable@vger.kernel.org |
| Fixes: b91c3e4ea756 ("landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER") |
| Link: https://lore.kernel.org/r/20240219190345.2928627-1-mic@digikod.net |
| Signed-off-by: Mickaël Salaün <mic@digikod.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| security/landlock/fs.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/security/landlock/fs.c |
| +++ b/security/landlock/fs.c |
| @@ -820,8 +820,8 @@ static int current_check_refer_path(stru |
| bool allow_parent1, allow_parent2; |
| access_mask_t access_request_parent1, access_request_parent2; |
| struct path mnt_dir; |
| - layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS], |
| - layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS]; |
| + layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS] = {}, |
| + layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS] = {}; |
| |
| if (!dom) |
| return 0; |