Skip to content

Commit 664f0f6

Browse files
committed
Merge tag 'sched_ext-for-7.1-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext
Pull sched_ext fixes from Tejun Heo: "The merge window pulled in the cgroup sub-scheduler infrastructure, and new AI reviews are accelerating bug reporting and fixing - hence the larger than usual fixes batch: - Use-after-frees during scheduler load/unload: - The disable path could free the BPF scheduler while deferred irq_work / kthread work was still in flight - cgroup setter callbacks read the active scheduler outside the rwsem that synchronizes against teardown Fix both, and reuse the disable drain in the enable error paths so the BPF JIT page can't be freed under live callbacks. - Several BPF op invocations didn't tell the framework which runqueue was already locked, so helper kfuncs that re-acquire the runqueue by CPU could deadlock on the held lock Fix the affected callsites, including recursive parent-into-child dispatch. - The hardlockup notifier ran from NMI but eventually took a non-NMI-safe lock. Bounce it through irq_work. - A handful of bugs in the new sub-scheduler hierarchy: - helper kfuncs hard-coded the root instead of resolving the caller's scheduler - the enable error path tried to disable per-task state that had never been initialized, and leaked cpus_read_lock on the way out - a sysfs object was leaked on every load/unload - the dispatch fast-path used the root scheduler instead of the task's - a couple of CONFIG #ifdef guards were misclassified - Verifier-time hardening: BPF programs of unrelated struct_ops types (e.g. tcp_congestion_ops) could call sched_ext kfuncs - a semantic bug and, once sub-sched was enabled, a KASAN out-of-bounds read. Now rejected at load. Plus a few NULL and cross-task argument checks on sched_ext kfuncs, and a selftest covering the new deny. - rhashtable (Herbert): restore the insecure_elasticity toggle and bounce the deferred-resize kick through irq_work to break a lock-order cycle observable from raw-spinlock callers. sched_ext's scheduler-instance hash is the first user of both. - The bypass-mode load balancer used file-scope cpumasks; with multiple scheduler instances now possible, those raced. Move to per-instance cpumasks, plus a follow-up to skip tasks whose recorded CPU is stale relative to the new owning runqueue. - Smaller fixes: - a dispatch queue's first-task tracking misbehaved when a parked iterator cursor sat in the list - the runqueue's next-class wasn't promoted on local-queue enqueue, leaving an SCX task behind RT in edge cases - the reference qmap scheduler stopped erroring on legitimate cross-scheduler task-storage misses" * tag 'sched_ext-for-7.1-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext: (26 commits) sched_ext: Fix scx_flush_disable_work() UAF race sched_ext: Call wakeup_preempt() in local_dsq_post_enq() sched_ext: Release cpus_read_lock on scx_link_sched() failure in root enable sched_ext: Reject NULL-sch callers in scx_bpf_task_set_slice/dsq_vtime sched_ext: Refuse cross-task select_cpu_from_kfunc calls sched_ext: Align cgroup #ifdef guards with SUB_SCHED vs GROUP_SCHED sched_ext: Make bypass LB cpumasks per-scheduler sched_ext: Pass held rq to SCX_CALL_OP() for core_sched_before sched_ext: Pass held rq to SCX_CALL_OP() for dump_cpu/dump_task sched_ext: Save and restore scx_locked_rq across SCX_CALL_OP sched_ext: Use dsq->first_task instead of list_empty() in dispatch_enqueue() FIFO-tail sched_ext: Resolve caller's scheduler in scx_bpf_destroy_dsq() / scx_bpf_dsq_nr_queued() sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters sched_ext: Don't disable tasks in scx_sub_enable_workfn() abort path sched_ext: Skip tasks with stale task_rq in bypass_lb_cpu() sched_ext: Guard scx_dsq_move() against NULL kit->dsq after failed iter_new sched_ext: Unregister sub_kset on scheduler disable sched_ext: Defer scx_hardlockup() out of NMI sched_ext: sync disable_irq_work in bpf_scx_unreg() sched_ext: Fix local_dsq_post_enq() to use task's scheduler in sub-sched ...
2 parents dca922e + d99f7a3 commit 664f0f6

11 files changed

Lines changed: 436 additions & 150 deletions

File tree

include/linux/rhashtable-types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/alloc_tag.h>
1313
#include <linux/atomic.h>
1414
#include <linux/compiler.h>
15+
#include <linux/irq_work_types.h>
1516
#include <linux/mutex.h>
1617
#include <linux/workqueue_types.h>
1718

@@ -49,6 +50,7 @@ typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg,
4950
* @head_offset: Offset of rhash_head in struct to be hashed
5051
* @max_size: Maximum size while expanding
5152
* @min_size: Minimum size while shrinking
53+
* @insecure_elasticity: Set to true to disable chain length checks
5254
* @automatic_shrinking: Enable automatic shrinking of tables
5355
* @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash)
5456
* @obj_hashfn: Function to hash object
@@ -61,6 +63,7 @@ struct rhashtable_params {
6163
u16 head_offset;
6264
unsigned int max_size;
6365
u16 min_size;
66+
bool insecure_elasticity;
6467
bool automatic_shrinking;
6568
rht_hashfn_t hashfn;
6669
rht_obj_hashfn_t obj_hashfn;
@@ -75,6 +78,7 @@ struct rhashtable_params {
7578
* @p: Configuration parameters
7679
* @rhlist: True if this is an rhltable
7780
* @run_work: Deferred worker to expand/shrink asynchronously
81+
* @run_irq_work: Bounces the @run_work kick through hard IRQ context.
7882
* @mutex: Mutex to protect current/future table swapping
7983
* @lock: Spin lock to protect walker list
8084
* @nelems: Number of elements in table
@@ -86,6 +90,7 @@ struct rhashtable {
8690
struct rhashtable_params p;
8791
bool rhlist;
8892
struct work_struct run_work;
93+
struct irq_work run_irq_work;
8994
struct mutex mutex;
9095
spinlock_t lock;
9196
atomic_t nelems;

include/linux/rhashtable.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <linux/err.h>
2222
#include <linux/errno.h>
23+
#include <linux/irq_work.h>
2324
#include <linux/jhash.h>
2425
#include <linux/list_nulls.h>
2526
#include <linux/workqueue.h>
@@ -821,14 +822,15 @@ static __always_inline void *__rhashtable_insert_fast(
821822
goto out;
822823
}
823824

824-
if (elasticity <= 0)
825+
if (elasticity <= 0 && !params.insecure_elasticity)
825826
goto slow_path;
826827

827828
data = ERR_PTR(-E2BIG);
828829
if (unlikely(rht_grow_above_max(ht, tbl)))
829830
goto out_unlock;
830831

831-
if (unlikely(rht_grow_above_100(ht, tbl)))
832+
if (unlikely(rht_grow_above_100(ht, tbl)) &&
833+
!params.insecure_elasticity)
832834
goto slow_path;
833835

834836
/* Inserting at head of list makes unlocking free. */
@@ -846,7 +848,7 @@ static __always_inline void *__rhashtable_insert_fast(
846848
rht_assign_unlock(tbl, bkt, obj, flags);
847849

848850
if (rht_grow_above_75(ht, tbl))
849-
schedule_work(&ht->run_work);
851+
irq_work_queue(&ht->run_irq_work);
850852

851853
data = NULL;
852854
out:

0 commit comments

Comments
 (0)