Patch "padata: Fix refcnt handling in padata_free_shell()" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    padata: Fix refcnt handling in padata_free_shell()

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     padata-fix-refcnt-handling-in-padata_free_shell.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 50d17a5fb3731553af7eb5245e1a9cd30d2e54db
Author: WangJinchao <wangjinchao@xxxxxxxxxxx>
Date:   Mon Oct 16 09:15:21 2023 +0800

    padata: Fix refcnt handling in padata_free_shell()
    
    [ Upstream commit 7ddc21e317b360c3444de3023bcc83b85fabae2f ]
    
    In a high-load arm64 environment, the pcrypt_aead01 test in LTP can lead
    to system UAF (Use-After-Free) issues. Due to the lengthy analysis of
    the pcrypt_aead01 function call, I'll describe the problem scenario
    using a simplified model:
    
    Suppose there's a user of padata named `user_function` that adheres to
    the padata requirement of calling `padata_free_shell` after `serial()`
    has been invoked, as demonstrated in the following code:
    
    ```c
    struct request {
        struct padata_priv padata;
        struct completion *done;
    };
    
    void parallel(struct padata_priv *padata) {
        do_something();
    }
    
    void serial(struct padata_priv *padata) {
        struct request *request = container_of(padata,
                                    struct request,
                                    padata);
        complete(request->done);
    }
    
    void user_function() {
        DECLARE_COMPLETION(done)
        padata->parallel = parallel;
        padata->serial = serial;
        padata_do_parallel();
        wait_for_completion(&done);
        padata_free_shell();
    }
    ```
    
    In the corresponding padata.c file, there's the following code:
    
    ```c
    static void padata_serial_worker(struct work_struct *serial_work) {
        ...
        cnt = 0;
    
        while (!list_empty(&local_list)) {
            ...
            padata->serial(padata);
            cnt++;
        }
    
        local_bh_enable();
    
        if (refcount_sub_and_test(cnt, &pd->refcnt))
            padata_free_pd(pd);
    }
    ```
    
    Because of the high system load and the accumulation of unexecuted
    softirq at this moment, `local_bh_enable()` in padata takes longer
    to execute than usual. Subsequently, when accessing `pd->refcnt`,
    `pd` has already been released by `padata_free_shell()`, resulting
    in a UAF issue with `pd->refcnt`.
    
    The fix is straightforward: add `refcount_dec_and_test` before calling
    `padata_free_pd` in `padata_free_shell`.
    
    Fixes: 07928d9bfc81 ("padata: Remove broken queue flushing")
    
    Signed-off-by: WangJinchao <wangjinchao@xxxxxxxxxxx>
    Acked-by: Daniel Jordan <daniel.m.jordan@xxxxxxxxxx>
    Acked-by: Daniel Jordan <daniel.m.jordan@xxxxxxxxxx>
    Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/padata.c b/kernel/padata.c
index de90af5fcbe6b..791d9cb07a501 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -1094,12 +1094,16 @@ EXPORT_SYMBOL(padata_alloc_shell);
  */
 void padata_free_shell(struct padata_shell *ps)
 {
+	struct parallel_data *pd;
+
 	if (!ps)
 		return;
 
 	mutex_lock(&ps->pinst->lock);
 	list_del(&ps->list);
-	padata_free_pd(rcu_dereference_protected(ps->pd, 1));
+	pd = rcu_dereference_protected(ps->pd, 1);
+	if (refcount_dec_and_test(&pd->refcnt))
+		padata_free_pd(pd);
 	mutex_unlock(&ps->pinst->lock);
 
 	kfree(ps);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux