Hello Andrii,

On Wed, Oct 23, 2024 at 09:41:59PM -0700, Andrii Nakryiko wrote:
>
> +static struct uprobe* hprobe_expire(struct hprobe *hprobe, bool get)
> +{
> +     enum hprobe_state hstate;
> +
> +     /*
> +      * return_instance's hprobe is protected by RCU.
> +      * Underlying uprobe is itself protected from reuse by SRCU.
> +      */
> +     lockdep_assert(rcu_read_lock_held() && 
> srcu_read_lock_held(&uretprobes_srcu));

I am hitting this warning in d082ecbc71e9e ("Linux 6.14-rc4") on
aarch64. I suppose this might happen on x86 as well, but I haven't
tested.

        WARNING: CPU: 28 PID: 158906 at kernel/events/uprobes.c:768 
hprobe_expire (kernel/events/uprobes.c:825)

        Call trace:
        hprobe_expire (kernel/events/uprobes.c:825) (P)
        uprobe_copy_process (kernel/events/uprobes.c:691 
kernel/events/uprobes.c:2103 kernel/events/uprobes.c:2142)
        copy_process (kernel/fork.c:2636)
        kernel_clone (kernel/fork.c:2815)
        __arm64_sys_clone (kernel/fork.c:? kernel/fork.c:2926 
kernel/fork.c:2926)
        invoke_syscall (arch/arm64/kernel/syscall.c:35 
arch/arm64/kernel/syscall.c:49)
        do_el0_svc (arch/arm64/kernel/syscall.c:139 
arch/arm64/kernel/syscall.c:151)
        el0_svc (arch/arm64/kernel/entry-common.c:165 
arch/arm64/kernel/entry-common.c:178 arch/arm64/kernel/entry-common.c:745)
        el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:797)
        el0t_64_sync (arch/arm64/kernel/entry.S:600)

I broke down that warning, and the problem is on related to
rcu_read_lock_held(), since RCU read lock does not seem to be held in
this path.

Reading this code, RCU read lock seems to protect old hprobe, which
doesn't seem so.

I am wondering if we need to protect it properly, something as:

        @@ -2089,7 +2092,9 @@ static int dup_utask(struct task_struct *t, 
struct uprobe_task *o_utask)
                                return -ENOMEM;

                        /* if uprobe is non-NULL, we'll have an extra refcount 
for uprobe */
        +               rcu_read_lock();
                        uprobe = hprobe_expire(&o->hprobe, true);
        +               rcu_write_lock();

                        /*
                        * New utask will have stable properly refcounted uprobe 
or

Reply via email to