configfs: Fix use-after-free when accessing sd->s_dentry [Linux 4.14.129]

configfs: Fix use-after-free when accessing sd->s_dentry [Linux 4.14.129]

This Linux kernel change "configfs: Fix use-after-free when accessing sd->s_dentry" is included in the Linux 4.14.129 release. This change is authored by Sahitya Tummala <stummala [at] codeaurora.org> on Thu Jan 3 16:48:15 2019 +0530. The commit for this change in Linux stable tree is 015cf9c (patch) which is from upstream commit f6122ed. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream f6122ed.

configfs: Fix use-after-free when accessing sd->s_dentry

[ Upstream commit f6122ed2a4f9c9c1c073ddf6308d1b2ac10e0781 ]

In the vfs_statx() context, during path lookup, the dentry gets
added to sd->s_dentry via configfs_attach_attr(). In the end,
vfs_statx() kills the dentry by calling path_put(), which invokes
configfs_d_iput(). Ideally, this dentry must be removed from
sd->s_dentry but it doesn't if the sd->s_count >= 3. As a result,
sd->s_dentry is holding reference to a stale dentry pointer whose
memory is already freed up. This results in use-after-free issue,
when this stale sd->s_dentry is accessed later in
configfs_readdir() path.

This issue can be easily reproduced, by running the LTP test case -
sh fs_racer_file_list.sh /config
(https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/fs/racer/fs_racer_file_list.sh)

Fixes: 76ae281f6307 ('configfs: fix race between dentry put and lookup')
Signed-off-by: Sahitya Tummala <[email protected]>
Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

There are 14 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 fs/configfs/dir.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index d7955dc..a1985a9 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -58,15 +58,13 @@ static void configfs_d_iput(struct dentry * dentry,
    if (sd) {
        /* Coordinate with configfs_readdir */
        spin_lock(&configfs_dirent_lock);
-       /* Coordinate with configfs_attach_attr where will increase
-        * sd->s_count and update sd->s_dentry to new allocated one.
-        * Only set sd->dentry to null when this dentry is the only
-        * sd owner.
-        * If not do so, configfs_d_iput may run just after
-        * configfs_attach_attr and set sd->s_dentry to null
-        * even it's still in use.
+       /*
+        * Set sd->s_dentry to null only when this dentry is the one
+        * that is going to be killed.  Otherwise configfs_d_iput may
+        * run just after configfs_attach_attr and set sd->s_dentry to
+        * NULL even it's still in use.
         */
-       if (atomic_read(&sd->s_count) <= 2)
+       if (sd->s_dentry == dentry)
            sd->s_dentry = NULL;

        spin_unlock(&configfs_dirent_lock);

Leave a Reply

Your email address will not be published. Required fields are marked *