]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - kernel/workqueue.c
arm64: Ensure execute-only permissions are not allowed without EPAN
[mirror_ubuntu-jammy-kernel.git] / kernel / workqueue.c
index 1b3eb1e9531f4ac71ebced9bac749ecea747064f..3f4d276685768cc7fc7061f114cffa7dc257745f 100644 (file)
@@ -867,8 +867,17 @@ void wq_worker_running(struct task_struct *task)
 
        if (!worker->sleeping)
                return;
+
+       /*
+        * If preempted by unbind_workers() between the WORKER_NOT_RUNNING check
+        * and the nr_running increment below, we may ruin the nr_running reset
+        * and leave with an unexpected pool->nr_running == 1 on the newly unbound
+        * pool. Protect against such race.
+        */
+       preempt_disable();
        if (!(worker->flags & WORKER_NOT_RUNNING))
                atomic_inc(&worker->pool->nr_running);
+       preempt_enable();
        worker->sleeping = 0;
 }
 
@@ -5384,9 +5393,6 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
        int ret = -EINVAL;
        cpumask_var_t saved_cpumask;
 
-       if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL))
-               return -ENOMEM;
-
        /*
         * Not excluding isolated cpus on purpose.
         * If the user wishes to include them, we allow that.
@@ -5394,6 +5400,15 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
        cpumask_and(cpumask, cpumask, cpu_possible_mask);
        if (!cpumask_empty(cpumask)) {
                apply_wqattrs_lock();
+               if (cpumask_equal(cpumask, wq_unbound_cpumask)) {
+                       ret = 0;
+                       goto out_unlock;
+               }
+
+               if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) {
+                       ret = -ENOMEM;
+                       goto out_unlock;
+               }
 
                /* save the old wq_unbound_cpumask. */
                cpumask_copy(saved_cpumask, wq_unbound_cpumask);
@@ -5406,10 +5421,11 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
                if (ret < 0)
                        cpumask_copy(wq_unbound_cpumask, saved_cpumask);
 
+               free_cpumask_var(saved_cpumask);
+out_unlock:
                apply_wqattrs_unlock();
        }
 
-       free_cpumask_var(saved_cpumask);
        return ret;
 }