FAILED: patch "[PATCH] landlock: Fix use-after-free of the source's parent directory" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 2c6dc792538260a8087ac5b22c31b3b8e47c85d6
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091642-android-strode-2706@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2c6dc792538260a8087ac5b22c31b3b8e47c85d6 Mon Sep 17 00:00:00 2001
From: Norbert Szetei <[email protected]>
Date: Sat, 22 Aug 2026 14:29:00 +0200
Subject: [PATCH] landlock: Fix use-after-free of the source's parent directory
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
current_check_refer_path() reads old_dentry->d_parent without holding a reference nor a lock on it, and then dereferences it in collect_domain_accesses() and in the audit record.
A reference on a child does not pin its parent: __d_move() reassigns dentry->d_parent and drops the reference the child held on its former parent. hook_path_rename() is not affected because the rename path calls lock_rename() before the hook, so the source cannot be reparented under it. hook_path_link() has no such protection: filename_linkat() holds a reference on the source dentry but neither locks nor references its parent, so a concurrent rename(2) can reparent the source while security_path_link() runs, and the former parent can then be removed and freed while the hook walks it.
A process can trigger this after entering a Landlock domain that handles at least one filesystem access right. The process can then race a linkat(2) loop against rename(2) and rmdir(2):
BUG: KASAN: slab-use-after-free in collect_domain_accesses+0x278/0x290 Read of size 4 at addr ffff888160bd53f4 by task llrepro2/549 collect_domain_accesses+0x278/0x290 current_check_refer_path+0x952/0x1120 security_path_link+0x1be/0x320 filename_linkat+0x342/0x6d0 __x64_sys_linkat+0xfa/0x150 Freed by task 562: kmem_cache_free+0x139/0x4c0 i_callback+0x4b/0x80 rcu_core+0x7dc/0x10a0
Take a reference on the dentry selected as the source parent, using dget() for the common-mount-root case and dget_parent() otherwise. Release it after the hierarchy walk and synchronous audit logging.
security/landlock/fs.c +12 -6
@@ -1298,11 +1298,12 @@ static int current_check_refer_path(struct dentry *const old_dentry,/* * old_dentry may be the root of the common mount point and * !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and -* OPEN_TREE_CLONE). We do not need to call dget(old_parent) because -* we keep a reference to old_dentry. +* OPEN_TREE_CLONE). Pin the dentry used as old_parent in either case. +* Otherwise, dget_parent() safely fetches and pins the current parent +* against a concurrent rename(2). */ - old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry : - old_dentry->d_parent; + old_parent = (old_dentry == mnt_dir.dentry) ?dget (old_dentry) : +dget_parent (old_dentry);/* new_dir->dentry is equal to new_dentry->d_parent */ allow_parent1 = collect_domain_accesses(subject->domain, mnt_dir.dentry,
@@ -1311,8 +1312,10 @@ static int current_check_refer_path(struct dentry *const old_dentry, allow_parent2 =collect_domain_accesses (subject->domain, mnt_dir.dentry, new_dir->dentry, &layer_masks_parent2); -if (allow_parent1 && allow_parent2) +if (allow_parent1 && allow_parent2) { +dput (old_parent);return 0 ; + }/* * To be able to compare source and destination domain access rights,
@@ -1324,8 +1327,10 @@ static int current_check_refer_path(struct dentry *const old_dentry, subject->domain, &mnt_dir, access_request_parent1, &layer_masks_parent1, &request1, old_dentry, access_request_parent2, &layer_masks_parent2, &request2, - exchange ? new_dentry : NULL)) + exchange ? new_dentry : NULL)) { +dput (old_parent);return 0 ; + }if (request1.access) { request1.audit.u.path.dentry = old_parent;
@@ -1335,6 +1340,7 @@ static int current_check_refer_path(struct dentry *const old_dentry, request2.audit.u.path.dentry = new_dir->dentry;landlock_log_denial (subject, &request2); } +dput (old_parent);/* * This prioritizes EACCES over EXDEV for all actions, including
Sasha Levin
maintainerPATCH 1/2 landlock: Clarify documentation for the IOCTL access right
From: Günther Noack <[email protected]>
[ Upstream commit 6abbb8703aeeb645a681ab6ad155e0b450413787 ]
Move the description of the LANDLOCK_ACCESS_FS_IOCTL_DEV access right together with the file access rights.
This group of access rights applies to files (in this case device files), and they can be added to file or directory inodes using landlock_add_rule(2). The check for that works the same for all file access rights, including LANDLOCK_ACCESS_FS_IOCTL_DEV.
Invoking ioctl(2) on directory FDs can not currently be restricted with Landlock. Having it grouped separately in the documentation is a remnant from earlier revisions of the LANDLOCK_ACCESS_FS_IOCTL_DEV patch set.
Stable-dep-of: 2c6dc7925382 ("landlock: Fix use-after-free of the source's parent directory")
--- include/uapi/linux/landlock.h | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
include/uapi/linux/landlock.h +17 -20
@@ -156,6 +156,23 @@ struct landlock_net_port_attr {* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with * ``O_TRUNC``. This access right is available since the third version of the * Landlock ABI. +* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened +* character or block device. +* +* This access right applies to all `ioctl(2)` commands implemented by device +* drivers. However, the following common IOCTL commands continue to be +* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right: +* +* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``), +* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``), +* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``, +* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``) +* * Some IOCTL commands which do not make sense when used with devices, but +* whose implementations are safe and return the right error codes +* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``) +* +* This access right is available since the fifth version of the Landlock +* ABI. * * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -216,26 +233,6 @@ struct landlock_net_port_attr {* If multiple requirements are not met, the ``EACCES`` error code takes * precedence over ``EXDEV``. * -* The following access right applies both to files and directories: -* -* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened -* character or block device. -* -* This access right applies to all `ioctl(2)` commands implemented by device -* drivers. However, the following common IOCTL commands continue to be -* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right: -* -* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``), -* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``), -* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``, -* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``) -* * Some IOCTL commands which do not make sense when used with devices, but -* whose implementations are safe and return the right error codes -* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``) -* -* This access right is available since the fifth version of the Landlock -* ABI. -* * .. warning:: * * It is currently not possible to restrict some file-related actions
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 landlock: Fix use-after-free of the source's parent directory
From: Norbert Szetei <[email protected]>
[ Upstream commit 2c6dc792538260a8087ac5b22c31b3b8e47c85d6 ]
current_check_refer_path() reads old_dentry->d_parent without holding a reference nor a lock on it, and then dereferences it in collect_domain_accesses() and in the audit record.
A reference on a child does not pin its parent: __d_move() reassigns dentry->d_parent and drops the reference the child held on its former parent. hook_path_rename() is not affected because the rename path calls lock_rename() before the hook, so the source cannot be reparented under it. hook_path_link() has no such protection: filename_linkat() holds a reference on the source dentry but neither locks nor references its parent, so a concurrent rename(2) can reparent the source while security_path_link() runs, and the former parent can then be removed and freed while the hook walks it.
A process can trigger this after entering a Landlock domain that handles at least one filesystem access right. The process can then race a linkat(2) loop against rename(2) and rmdir(2):
BUG: KASAN: slab-use-after-free in collect_domain_accesses+0x278/0x290 Read of size 4 at addr ffff888160bd53f4 by task llrepro2/549 collect_domain_accesses+0x278/0x290 current_check_refer_path+0x952/0x1120 security_path_link+0x1be/0x320 filename_linkat+0x342/0x6d0 __x64_sys_linkat+0xfa/0x150 Freed by task 562: kmem_cache_free+0x139/0x4c0 i_callback+0x4b/0x80 rcu_core+0x7dc/0x10a0
Take a reference on the dentry selected as the source parent, using dget() for the common-mount-root case and dget_parent() otherwise. Release it after the hierarchy walk and synchronous audit logging.
--- security/landlock/fs.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
security/landlock/fs.c +12 -6
@@ -1192,11 +1192,12 @@ static int current_check_refer_path(struct dentry *const old_dentry,/* * old_dentry may be the root of the common mount point and * !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and -* OPEN_TREE_CLONE). We do not need to call dget(old_parent) because -* we keep a reference to old_dentry. +* OPEN_TREE_CLONE). Pin the dentry used as old_parent in either case. +* Otherwise, dget_parent() safely fetches and pins the current parent +* against a concurrent rename(2). */ - old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry : - old_dentry->d_parent; + old_parent = (old_dentry == mnt_dir.dentry) ?dget (old_dentry) : +dget_parent (old_dentry);/* new_dir->dentry is equal to new_dentry->d_parent */ allow_parent1 = collect_domain_accesses(dom, mnt_dir.dentry, old_parent,
@@ -1204,8 +1205,10 @@ static int current_check_refer_path(struct dentry *const old_dentry, allow_parent2 =collect_domain_accesses ( dom, mnt_dir.dentry, new_dir->dentry, &layer_masks_parent2); -if (allow_parent1 && allow_parent2) +if (allow_parent1 && allow_parent2) { +dput (old_parent);return 0 ; + }/* * To be able to compare source and destination domain access rights,
@@ -1216,8 +1219,11 @@ static int current_check_refer_path(struct dentry *const old_dentry,if (is_access_to_paths_allowed ( dom, &mnt_dir, access_request_parent1, &layer_masks_parent1, old_dentry, access_request_parent2, &layer_masks_parent2, - exchange ? new_dentry :NULL )) + exchange ? new_dentry :NULL )) { +dput (old_parent);return 0 ; + } +dput (old_parent);/* * This prioritizes EACCES over EXDEV for all actions, including
Signature · 1 line
2.53.0