mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq()
@ 2025-08-01 14:17 Christian Loehle
  2025-08-01 14:17 ` [PATCH 1/3] sched_ext: Mark scx_bpf_cpu_rq as NULL returnable Christian Loehle
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:17 UTC (permalink / raw)
  To: christian.loehle, linux-kernel, sched-ext, tj, void, arighi; +Cc: mingo, peterz

scx_bpf_cpu_rq() currently allows accessing struct rq fields without
holding the associated rq.
It is being used by scx_cosmos, scx_flash, scx_lavd, scx_layered, and
scx_tickless. Fortunately it is only ever used to fetch rq->curr.
So provide an alternative scx_bpf_remote_curr() that doesn't expose
struct rq and harden scx_bpf_cpu_rq() by ensuring we hold the rq lock.

This also simplifies scx code from:

rq = scx_bpf_cpu_rq(cpu);
if (!rq)
	return;
p = rq->curr
if (!p)
	return;
/* ... Do something with p */

into:

p = scx_bpf_remote_curr(cpu);
if (!p)
	return;
/* ... Do something with p */


Patch 1 was previously submitted and can be applied independently of
the other two.
https://lore.kernel.org/lkml/43a9cbdc-5121-4dc8-8438-0f01c90a4687@arm.com/
https://lore.kernel.org/lkml/0b8111c6-1b14-41dc-a674-14a6361992b3@arm.com/

Christian Loehle (3):
  sched_ext: Mark scx_bpf_cpu_rq as NULL returnable
  sched_ext: Provide scx_bpf_remote_curr()
  sched_ext: Guarantee rq lock on scx_bpf_cpu_rq()

 kernel/sched/ext.c                       | 21 ++++++++++++++++++---
 tools/sched_ext/include/scx/common.bpf.h |  1 +
 2 files changed, 19 insertions(+), 3 deletions(-)

--
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] sched_ext: Mark scx_bpf_cpu_rq as NULL returnable
  2025-08-01 14:17 [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Christian Loehle
@ 2025-08-01 14:17 ` Christian Loehle
  2025-08-01 14:17 ` [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr() Christian Loehle
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:17 UTC (permalink / raw)
  To: christian.loehle, linux-kernel, sched-ext, tj, void, arighi; +Cc: mingo, peterz

scx_bpf_cpu_rq() obviously returns NULL on invalid cpu.
Mark it as such.
While kf_cpu_valid() will trigger scx_ops_error() that leads
to the BPF scheduler exiting, this isn't guaranteed to be immediate,
allowing for a dereference of a NULL scx_bpf_cpu_rq() return value.

Cc: stable@vger.kernel.org
Fixes: 6203ef73fa5c ("sched/ext: Add BPF function to fetch rq")
Signed-off-by: Christian Loehle <christian.loehle@arm.com>
Acked-by: Andrea Righi <arighi@nvidia.com>
---
 kernel/sched/ext.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 7dd5cbcb7a06..b734f55f3318 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -7599,7 +7599,7 @@ BTF_ID_FLAGS(func, scx_bpf_get_online_cpumask, KF_ACQUIRE)
 BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE)
 BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU)
 BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU)
-BTF_ID_FLAGS(func, scx_bpf_cpu_rq)
+BTF_ID_FLAGS(func, scx_bpf_cpu_rq, KF_RET_NULL)
 #ifdef CONFIG_CGROUP_SCHED
 BTF_ID_FLAGS(func, scx_bpf_task_cgroup, KF_RCU | KF_ACQUIRE)
 #endif
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr()
  2025-08-01 14:17 [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Christian Loehle
  2025-08-01 14:17 ` [PATCH 1/3] sched_ext: Mark scx_bpf_cpu_rq as NULL returnable Christian Loehle
@ 2025-08-01 14:17 ` Christian Loehle
  2025-08-01 14:47   ` Andrea Righi
  2025-08-01 14:17 ` [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq() Christian Loehle
  2025-08-01 14:39 ` [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Andrea Righi
  3 siblings, 1 reply; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:17 UTC (permalink / raw)
  To: christian.loehle, linux-kernel, sched-ext, tj, void, arighi; +Cc: mingo, peterz

Provide scx_bpf_remote_curr() as a way for scx schedulers to
check the curr task of a remote rq, without assuming its lock
or acquiring any.

Many scx schedulers make use of scx_bpf_cpu_rq() to check a
remote curr (e.g. to see if it should be preempted). This is
problematic because scx_bpf_cpu_rq() provides access to all
fields of struct rq, most of which aren't safe to use without
holding the associated rq lock.

Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
 kernel/sched/ext.c                       | 15 +++++++++++++++
 tools/sched_ext/include/scx/common.bpf.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index b734f55f3318..92e66bb0b5f2 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -7436,6 +7436,20 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
 	return cpu_rq(cpu);
 }
 
+/**
+ * scx_bpf_remote_curr - Fetch the curr of a rq without acquiring its rq lock
+ * @cpu: CPU of the rq
+ *
+ * Neither a rq lock nor a task reference is acquired.
+ */
+__bpf_kfunc struct task_struct *scx_bpf_remote_curr(s32 cpu)
+{
+	if (!kf_cpu_valid(cpu, NULL))
+		return NULL;
+
+	return cpu_rq(cpu)->curr;
+}
+
 /**
  * scx_bpf_task_cgroup - Return the sched cgroup of a task
  * @p: task of interest
@@ -7600,6 +7614,7 @@ BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE)
 BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU)
 BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU)
 BTF_ID_FLAGS(func, scx_bpf_cpu_rq, KF_RET_NULL)
+BTF_ID_FLAGS(func, scx_bpf_remote_curr, KF_RET_NULL)
 #ifdef CONFIG_CGROUP_SCHED
 BTF_ID_FLAGS(func, scx_bpf_task_cgroup, KF_RCU | KF_ACQUIRE)
 #endif
diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
index d4e21558e982..e5d4ef124532 100644
--- a/tools/sched_ext/include/scx/common.bpf.h
+++ b/tools/sched_ext/include/scx/common.bpf.h
@@ -91,6 +91,7 @@ s32 scx_bpf_pick_any_cpu(const cpumask_t *cpus_allowed, u64 flags) __ksym;
 bool scx_bpf_task_running(const struct task_struct *p) __ksym;
 s32 scx_bpf_task_cpu(const struct task_struct *p) __ksym;
 struct rq *scx_bpf_cpu_rq(s32 cpu) __ksym;
+struct task_struct *scx_bpf_remote_curr(s32 cpu) __ksym;
 struct cgroup *scx_bpf_task_cgroup(struct task_struct *p) __ksym __weak;
 u64 scx_bpf_now(void) __ksym __weak;
 void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __weak;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq()
  2025-08-01 14:17 [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Christian Loehle
  2025-08-01 14:17 ` [PATCH 1/3] sched_ext: Mark scx_bpf_cpu_rq as NULL returnable Christian Loehle
  2025-08-01 14:17 ` [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr() Christian Loehle
@ 2025-08-01 14:17 ` Christian Loehle
  2025-08-01 14:51   ` Andrea Righi
  2025-08-01 14:39 ` [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Andrea Righi
  3 siblings, 1 reply; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:17 UTC (permalink / raw)
  To: christian.loehle, linux-kernel, sched-ext, tj, void, arighi; +Cc: mingo, peterz

Most fields in scx_bpf_cpu_rq() assume that its rq_lock is held.
Furthermore they become meaningless without rq lock, too.
Only return scx_bpf_cpu_rq() when we hold rq lock of that rq.

All upstream scx schedulers can be converted into the new
scx_bpf_remote_curr() instead.

Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
 kernel/sched/ext.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 92e66bb0b5f2..627df3088fd0 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -7425,7 +7425,7 @@ __bpf_kfunc s32 scx_bpf_task_cpu(const struct task_struct *p)
 }
 
 /**
- * scx_bpf_cpu_rq - Fetch the rq of a CPU
+ * scx_bpf_cpu_rq - Fetch the rq of a CPU if its rq lock is currently held
  * @cpu: CPU of the rq
  */
 __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
@@ -7433,7 +7433,7 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
 	if (!kf_cpu_valid(cpu, NULL))
 		return NULL;
 
-	return cpu_rq(cpu);
+	return this_cpu_read(locked_rq) == cpu_rq(cpu) ? cpu_rq(cpu) : NULL;
 }
 
 /**
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq()
  2025-08-01 14:17 [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Christian Loehle
                   ` (2 preceding siblings ...)
  2025-08-01 14:17 ` [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq() Christian Loehle
@ 2025-08-01 14:39 ` Andrea Righi
  3 siblings, 0 replies; 9+ messages in thread
From: Andrea Righi @ 2025-08-01 14:39 UTC (permalink / raw)
  To: Christian Loehle; +Cc: linux-kernel, sched-ext, tj, void, mingo, peterz

Hi Christian,

thanks for tackling this! Comments below.

On Fri, Aug 01, 2025 at 03:17:38PM +0100, Christian Loehle wrote:
> scx_bpf_cpu_rq() currently allows accessing struct rq fields without
> holding the associated rq.
> It is being used by scx_cosmos, scx_flash, scx_lavd, scx_layered, and
> scx_tickless. Fortunately it is only ever used to fetch rq->curr.
> So provide an alternative scx_bpf_remote_curr() that doesn't expose
> struct rq and harden scx_bpf_cpu_rq() by ensuring we hold the rq lock.
> 
> This also simplifies scx code from:
> 
> rq = scx_bpf_cpu_rq(cpu);
> if (!rq)
> 	return;
> p = rq->curr
> if (!p)
> 	return;
> /* ... Do something with p */
> 
> into:
> 
> p = scx_bpf_remote_curr(cpu);
> if (!p)
> 	return;
> /* ... Do something with p */

To be 100% correct I think we should do something similar to
bpf_task_from_pid(), acquire a reference to the task and release it via
bpf_task_release().

Basically:

 p = scx_bpf_remote_curr(cpu);
 if (!p)
 	return;
 /* ... Do something with p */
 bpf_task_release(p);

Thanks
-Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr()
  2025-08-01 14:17 ` [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr() Christian Loehle
@ 2025-08-01 14:47   ` Andrea Righi
  2025-08-01 14:58     ` Christian Loehle
  0 siblings, 1 reply; 9+ messages in thread
From: Andrea Righi @ 2025-08-01 14:47 UTC (permalink / raw)
  To: Christian Loehle; +Cc: linux-kernel, sched-ext, tj, void, mingo, peterz

On Fri, Aug 01, 2025 at 03:17:40PM +0100, Christian Loehle wrote:
> Provide scx_bpf_remote_curr() as a way for scx schedulers to
> check the curr task of a remote rq, without assuming its lock
> or acquiring any.
> 
> Many scx schedulers make use of scx_bpf_cpu_rq() to check a
> remote curr (e.g. to see if it should be preempted). This is
> problematic because scx_bpf_cpu_rq() provides access to all
> fields of struct rq, most of which aren't safe to use without
> holding the associated rq lock.
> 
> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
> ---
>  kernel/sched/ext.c                       | 15 +++++++++++++++
>  tools/sched_ext/include/scx/common.bpf.h |  1 +
>  2 files changed, 16 insertions(+)
> 
> diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
> index b734f55f3318..92e66bb0b5f2 100644
> --- a/kernel/sched/ext.c
> +++ b/kernel/sched/ext.c
> @@ -7436,6 +7436,20 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
>  	return cpu_rq(cpu);
>  }
>  
> +/**
> + * scx_bpf_remote_curr - Fetch the curr of a rq without acquiring its rq lock
> + * @cpu: CPU of the rq
> + *
> + * Neither a rq lock nor a task reference is acquired.
> + */
> +__bpf_kfunc struct task_struct *scx_bpf_remote_curr(s32 cpu)
> +{
> +	if (!kf_cpu_valid(cpu, NULL))
> +		return NULL;
> +
> +	return cpu_rq(cpu)->curr;
> +}

As mentioned in my previou comment, this should be something like:

 if (!kf_cpu_valid(cpu, NULL))
 	return NULL;

 rcu_read_lock();
 p = cpu_rq(cpu)->curr;
 if (p)
 	p = bpf_task_acquire(p);
 rcu_read_unlock();

 return p;

We may still race with CPU hotplugging, but I think it's not always
possible to use cpus_read_lock/unlock() here. Also, most of the scx
schedulers are restarted on CPU hotplugging events, so... one thing at a
time. :)

> +
>  /**
>   * scx_bpf_task_cgroup - Return the sched cgroup of a task
>   * @p: task of interest
> @@ -7600,6 +7614,7 @@ BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE)
>  BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU)
>  BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU)
>  BTF_ID_FLAGS(func, scx_bpf_cpu_rq, KF_RET_NULL)
> +BTF_ID_FLAGS(func, scx_bpf_remote_curr, KF_RET_NULL)
>  #ifdef CONFIG_CGROUP_SCHED
>  BTF_ID_FLAGS(func, scx_bpf_task_cgroup, KF_RCU | KF_ACQUIRE)
>  #endif
> diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
> index d4e21558e982..e5d4ef124532 100644
> --- a/tools/sched_ext/include/scx/common.bpf.h
> +++ b/tools/sched_ext/include/scx/common.bpf.h
> @@ -91,6 +91,7 @@ s32 scx_bpf_pick_any_cpu(const cpumask_t *cpus_allowed, u64 flags) __ksym;
>  bool scx_bpf_task_running(const struct task_struct *p) __ksym;
>  s32 scx_bpf_task_cpu(const struct task_struct *p) __ksym;
>  struct rq *scx_bpf_cpu_rq(s32 cpu) __ksym;
> +struct task_struct *scx_bpf_remote_curr(s32 cpu) __ksym;
>  struct cgroup *scx_bpf_task_cgroup(struct task_struct *p) __ksym __weak;
>  u64 scx_bpf_now(void) __ksym __weak;
>  void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __weak;
> -- 
> 2.34.1
> 

-Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq()
  2025-08-01 14:17 ` [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq() Christian Loehle
@ 2025-08-01 14:51   ` Andrea Righi
  2025-08-01 14:54     ` Christian Loehle
  0 siblings, 1 reply; 9+ messages in thread
From: Andrea Righi @ 2025-08-01 14:51 UTC (permalink / raw)
  To: Christian Loehle; +Cc: linux-kernel, sched-ext, tj, void, mingo, peterz

On Fri, Aug 01, 2025 at 03:17:41PM +0100, Christian Loehle wrote:
> Most fields in scx_bpf_cpu_rq() assume that its rq_lock is held.
> Furthermore they become meaningless without rq lock, too.
> Only return scx_bpf_cpu_rq() when we hold rq lock of that rq.
> 
> All upstream scx schedulers can be converted into the new
> scx_bpf_remote_curr() instead.
> 
> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
> ---
>  kernel/sched/ext.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
> index 92e66bb0b5f2..627df3088fd0 100644
> --- a/kernel/sched/ext.c
> +++ b/kernel/sched/ext.c
> @@ -7425,7 +7425,7 @@ __bpf_kfunc s32 scx_bpf_task_cpu(const struct task_struct *p)
>  }
>  
>  /**
> - * scx_bpf_cpu_rq - Fetch the rq of a CPU
> + * scx_bpf_cpu_rq - Fetch the rq of a CPU if its rq lock is currently held
>   * @cpu: CPU of the rq
>   */
>  __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
> @@ -7433,7 +7433,7 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
>  	if (!kf_cpu_valid(cpu, NULL))
>  		return NULL;
>  
> -	return cpu_rq(cpu);
> +	return this_cpu_read(locked_rq) == cpu_rq(cpu) ? cpu_rq(cpu) : NULL;

Maybe we should consider an access to an unlocked rq as invalid and trigger
scx_exit(), similar to what we do with the kf_cpu_valid() check?

Also heads up that locked_rq has been renamed scx_locked_rq_state in 6.17.

>  }
>  
>  /**
> -- 
> 2.34.1
> 

Thanks,
-Andrea

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq()
  2025-08-01 14:51   ` Andrea Righi
@ 2025-08-01 14:54     ` Christian Loehle
  0 siblings, 0 replies; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:54 UTC (permalink / raw)
  To: Andrea Righi; +Cc: linux-kernel, sched-ext, tj, void, mingo, peterz

On 8/1/25 15:51, Andrea Righi wrote:
> On Fri, Aug 01, 2025 at 03:17:41PM +0100, Christian Loehle wrote:
>> Most fields in scx_bpf_cpu_rq() assume that its rq_lock is held.
>> Furthermore they become meaningless without rq lock, too.
>> Only return scx_bpf_cpu_rq() when we hold rq lock of that rq.
>>
>> All upstream scx schedulers can be converted into the new
>> scx_bpf_remote_curr() instead.
>>
>> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
>> ---
>>  kernel/sched/ext.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
>> index 92e66bb0b5f2..627df3088fd0 100644
>> --- a/kernel/sched/ext.c
>> +++ b/kernel/sched/ext.c
>> @@ -7425,7 +7425,7 @@ __bpf_kfunc s32 scx_bpf_task_cpu(const struct task_struct *p)
>>  }
>>  
>>  /**
>> - * scx_bpf_cpu_rq - Fetch the rq of a CPU
>> + * scx_bpf_cpu_rq - Fetch the rq of a CPU if its rq lock is currently held
>>   * @cpu: CPU of the rq
>>   */
>>  __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
>> @@ -7433,7 +7433,7 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
>>  	if (!kf_cpu_valid(cpu, NULL))
>>  		return NULL;
>>  
>> -	return cpu_rq(cpu);
>> +	return this_cpu_read(locked_rq) == cpu_rq(cpu) ? cpu_rq(cpu) : NULL;
> 
> Maybe we should consider an access to an unlocked rq as invalid and trigger
> scx_exit(), similar to what we do with the kf_cpu_valid() check?

Makes sense to me!

> 
> Also heads up that locked_rq has been renamed scx_locked_rq_state in 6.17.

Ah, thanks! I'll rebase!

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr()
  2025-08-01 14:47   ` Andrea Righi
@ 2025-08-01 14:58     ` Christian Loehle
  0 siblings, 0 replies; 9+ messages in thread
From: Christian Loehle @ 2025-08-01 14:58 UTC (permalink / raw)
  To: Andrea Righi; +Cc: linux-kernel, sched-ext, tj, void, mingo, peterz

On 8/1/25 15:47, Andrea Righi wrote:
> On Fri, Aug 01, 2025 at 03:17:40PM +0100, Christian Loehle wrote:
>> Provide scx_bpf_remote_curr() as a way for scx schedulers to
>> check the curr task of a remote rq, without assuming its lock
>> or acquiring any.
>>
>> Many scx schedulers make use of scx_bpf_cpu_rq() to check a
>> remote curr (e.g. to see if it should be preempted). This is
>> problematic because scx_bpf_cpu_rq() provides access to all
>> fields of struct rq, most of which aren't safe to use without
>> holding the associated rq lock.
>>
>> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
>> ---
>>  kernel/sched/ext.c                       | 15 +++++++++++++++
>>  tools/sched_ext/include/scx/common.bpf.  |  1 +
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
>> index b734f55f3318..92e66bb0b5f2 100644
>> --- a/kernel/sched/ext.c
>> +++ b/kernel/sched/ext.c
>> @@ -7436,6 +7436,20 @@ __bpf_kfunc struct rq *scx_bpf_cpu_rq(s32 cpu)
>>  	return cpu_rq(cpu);
>>  }
>>  
>> +/**
>> + * scx_bpf_remote_curr - Fetch the curr of a rq without acquiring its rq lock
>> + * @cpu: CPU of the rq
>> + *
>> + * Neither a rq lock nor a task reference is acquired.
>> + */
>> +__bpf_kfunc struct task_struct *scx_bpf_remote_curr(s32 cpu)
>> +{
>> +	if (!kf_cpu_valid(cpu, NULL))
>> +		return NULL;
>> +
>> +	return cpu_rq(cpu)->curr;
>> +}
> 
> As mentioned in my previou comment, this should be something like:
> 
>  if (!kf_cpu_valid(cpu, NULL))
>  	return NULL;
> 
>  rcu_read_lock();
>  p = cpu_rq(cpu)->curr;
>  if (p)
>  	p = bpf_task_acquire(p);
>  rcu_read_unlock();
> 
>  return p;

Alright, that's actually what I had at first, but went with the
drop-in-replacement that doesn't acquire.
I'll resend with an acquire.
Thanks, Andrea!

> 
> We may still race with CPU hotplugging, but I think it's not always
> possible to use cpus_read_lock/unlock() here. Also, most of the scx
> schedulers are restarted on CPU hotplugging events, so... one thing at a
> time. :)
> 
>> +
>>  /**
>>   * scx_bpf_task_cgroup - Return the sched cgroup of a task
>>   * @p: task of interest
>> @@ -7600,6 +7614,7 @@ BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE)
>>  BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU)
>>  BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU)
>>  BTF_ID_FLAGS(func, scx_bpf_cpu_rq, KF_RET_NULL)
>> +BTF_ID_FLAGS(func, scx_bpf_remote_curr, KF_RET_NULL)
>>  #ifdef CONFIG_CGROUP_SCHED
>>  BTF_ID_FLAGS(func, scx_bpf_task_cgroup, KF_RCU | KF_ACQUIRE)
>>  #endif
>> diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
>> index d4e21558e982..e5d4ef124532 100644
>> --- a/tools/sched_ext/include/scx/common.bpf.h
>> +++ b/tools/sched_ext/include/scx/common.bpf.h
>> @@ -91,6 +91,7 @@ s32 scx_bpf_pick_any_cpu(const cpumask_t *cpus_allowed, u64 flags) __ksym;
>>  bool scx_bpf_task_running(const struct task_struct *p) __ksym;
>>  s32 scx_bpf_task_cpu(const struct task_struct *p) __ksym;
>>  struct rq *scx_bpf_cpu_rq(s32 cpu) __ksym;
>> +struct task_struct *scx_bpf_remote_curr(s32 cpu) __ksym;
>>  struct cgroup *scx_bpf_task_cgroup(struct task_struct *p) __ksym __weak;
>>  u64 scx_bpf_now(void) __ksym __weak;
>>  void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __weak;
>> -- 
>> 2.34.1
>>
> 
> -Andrea


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-08-01 14:58 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-01 14:17 [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Christian Loehle
2025-08-01 14:17 ` [PATCH 1/3] sched_ext: Mark scx_bpf_cpu_rq as NULL returnable Christian Loehle
2025-08-01 14:17 ` [PATCH 2/3] sched_ext: Provide scx_bpf_remote_curr() Christian Loehle
2025-08-01 14:47   ` Andrea Righi
2025-08-01 14:58     ` Christian Loehle
2025-08-01 14:17 ` [PATCH 3/3] sched_ext: Guarantee rq lock on scx_bpf_cpu_rq() Christian Loehle
2025-08-01 14:51   ` Andrea Righi
2025-08-01 14:54     ` Christian Loehle
2025-08-01 14:39 ` [PATCH 0/3] sched_ext: Harden scx_bpf_cpu_rq() Andrea Righi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®