@@ -1862,8 +1862,13 @@ struct migration_arg {
18621862 struct set_affinity_pending * pending ;
18631863};
18641864
1865+ /*
1866+ * @refs: number of wait_for_completion()
1867+ * @stop_pending: is @stop_work in use
1868+ */
18651869struct set_affinity_pending {
18661870 refcount_t refs ;
1871+ unsigned int stop_pending ;
18671872 struct completion done ;
18681873 struct cpu_stop_work stop_work ;
18691874 struct migration_arg arg ;
@@ -1898,8 +1903,8 @@ static struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf,
18981903 */
18991904static int migration_cpu_stop (void * data )
19001905{
1901- struct set_affinity_pending * pending ;
19021906 struct migration_arg * arg = data ;
1907+ struct set_affinity_pending * pending = arg -> pending ;
19031908 struct task_struct * p = arg -> task ;
19041909 int dest_cpu = arg -> dest_cpu ;
19051910 struct rq * rq = this_rq ();
@@ -1921,7 +1926,6 @@ static int migration_cpu_stop(void *data)
19211926 raw_spin_lock (& p -> pi_lock );
19221927 rq_lock (rq , & rf );
19231928
1924- pending = p -> migration_pending ;
19251929 /*
19261930 * If task_rq(p) != rq, it cannot be migrated here, because we're
19271931 * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
@@ -1932,21 +1936,14 @@ static int migration_cpu_stop(void *data)
19321936 goto out ;
19331937
19341938 if (pending ) {
1935- p -> migration_pending = NULL ;
1939+ if (p -> migration_pending == pending )
1940+ p -> migration_pending = NULL ;
19361941 complete = true;
19371942 }
19381943
1939- /* migrate_enable() -- we must not race against SCA */
19401944 if (dest_cpu < 0 ) {
1941- /*
1942- * When this was migrate_enable() but we no longer
1943- * have a @pending, a concurrent SCA 'fixed' things
1944- * and we should be valid again. Nothing to do.
1945- */
1946- if (!pending ) {
1947- WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ));
1945+ if (cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ))
19481946 goto out ;
1949- }
19501947
19511948 dest_cpu = cpumask_any_distribute (& p -> cpus_mask );
19521949 }
@@ -1956,7 +1953,14 @@ static int migration_cpu_stop(void *data)
19561953 else
19571954 p -> wake_cpu = dest_cpu ;
19581955
1959- } else if (dest_cpu < 0 || pending ) {
1956+ /*
1957+ * XXX __migrate_task() can fail, at which point we might end
1958+ * up running on a dodgy CPU, AFAICT this can only happen
1959+ * during CPU hotplug, at which point we'll get pushed out
1960+ * anyway, so it's probably not a big deal.
1961+ */
1962+
1963+ } else if (pending ) {
19601964 /*
19611965 * This happens when we get migrated between migrate_enable()'s
19621966 * preempt_enable() and scheduling the stopper task. At that
@@ -1971,43 +1975,32 @@ static int migration_cpu_stop(void *data)
19711975 * ->pi_lock, so the allowed mask is stable - if it got
19721976 * somewhere allowed, we're done.
19731977 */
1974- if (pending && cpumask_test_cpu (task_cpu (p ), p -> cpus_ptr )) {
1975- p -> migration_pending = NULL ;
1978+ if (cpumask_test_cpu (task_cpu (p ), p -> cpus_ptr )) {
1979+ if (p -> migration_pending == pending )
1980+ p -> migration_pending = NULL ;
19761981 complete = true;
19771982 goto out ;
19781983 }
19791984
1980- /*
1981- * When this was migrate_enable() but we no longer have an
1982- * @pending, a concurrent SCA 'fixed' things and we should be
1983- * valid again. Nothing to do.
1984- */
1985- if (!pending ) {
1986- WARN_ON_ONCE (!cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask ));
1987- goto out ;
1988- }
1989-
19901985 /*
19911986 * When migrate_enable() hits a rq mis-match we can't reliably
19921987 * determine is_migration_disabled() and so have to chase after
19931988 * it.
19941989 */
1990+ WARN_ON_ONCE (!pending -> stop_pending );
19951991 task_rq_unlock (rq , p , & rf );
19961992 stop_one_cpu_nowait (task_cpu (p ), migration_cpu_stop ,
19971993 & pending -> arg , & pending -> stop_work );
19981994 return 0 ;
19991995 }
20001996out :
1997+ if (pending )
1998+ pending -> stop_pending = false;
20011999 task_rq_unlock (rq , p , & rf );
20022000
20032001 if (complete )
20042002 complete_all (& pending -> done );
20052003
2006- /* For pending->{arg,stop_work} */
2007- pending = arg -> pending ;
2008- if (pending && refcount_dec_and_test (& pending -> refs ))
2009- wake_up_var (& pending -> refs );
2010-
20112004 return 0 ;
20122005}
20132006
@@ -2194,11 +2187,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
21942187 int dest_cpu , unsigned int flags )
21952188{
21962189 struct set_affinity_pending my_pending = { }, * pending = NULL ;
2197- struct migration_arg arg = {
2198- .task = p ,
2199- .dest_cpu = dest_cpu ,
2200- };
2201- bool complete = false;
2190+ bool stop_pending , complete = false;
22022191
22032192 /* Can the task run on the task's current CPU? If so, we're done */
22042193 if (cpumask_test_cpu (task_cpu (p ), & p -> cpus_mask )) {
@@ -2210,12 +2199,16 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22102199 push_task = get_task_struct (p );
22112200 }
22122201
2202+ /*
2203+ * If there are pending waiters, but no pending stop_work,
2204+ * then complete now.
2205+ */
22132206 pending = p -> migration_pending ;
2214- if (pending ) {
2215- refcount_inc (& pending -> refs );
2207+ if (pending && !pending -> stop_pending ) {
22162208 p -> migration_pending = NULL ;
22172209 complete = true;
22182210 }
2211+
22192212 task_rq_unlock (rq , p , rf );
22202213
22212214 if (push_task ) {
@@ -2224,7 +2217,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22242217 }
22252218
22262219 if (complete )
2227- goto do_complete ;
2220+ complete_all ( & pending -> done ) ;
22282221
22292222 return 0 ;
22302223 }
@@ -2235,6 +2228,12 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22352228 /* Install the request */
22362229 refcount_set (& my_pending .refs , 1 );
22372230 init_completion (& my_pending .done );
2231+ my_pending .arg = (struct migration_arg ) {
2232+ .task = p ,
2233+ .dest_cpu = -1 , /* any */
2234+ .pending = & my_pending ,
2235+ };
2236+
22382237 p -> migration_pending = & my_pending ;
22392238 } else {
22402239 pending = p -> migration_pending ;
@@ -2259,60 +2258,59 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22592258 return - EINVAL ;
22602259 }
22612260
2262- if (flags & SCA_MIGRATE_ENABLE ) {
2263-
2264- refcount_inc (& pending -> refs ); /* pending->{arg,stop_work} */
2265- p -> migration_flags &= ~MDF_PUSH ;
2266- task_rq_unlock (rq , p , rf );
2267-
2268- pending -> arg = (struct migration_arg ) {
2269- .task = p ,
2270- .dest_cpu = -1 ,
2271- .pending = pending ,
2272- };
2273-
2274- stop_one_cpu_nowait (cpu_of (rq ), migration_cpu_stop ,
2275- & pending -> arg , & pending -> stop_work );
2276-
2277- return 0 ;
2278- }
2279-
22802261 if (task_running (rq , p ) || p -> state == TASK_WAKING ) {
22812262 /*
2282- * Lessen races (and headaches) by delegating
2283- * is_migration_disabled(p) checks to the stopper, which will
2284- * run on the same CPU as said p .
2263+ * MIGRATE_ENABLE gets here because 'p == current', but for
2264+ * anything else we cannot do is_migration_disabled(), punt
2265+ * and have the stopper function handle it all race-free .
22852266 */
2267+ stop_pending = pending -> stop_pending ;
2268+ if (!stop_pending )
2269+ pending -> stop_pending = true;
2270+
2271+ if (flags & SCA_MIGRATE_ENABLE )
2272+ p -> migration_flags &= ~MDF_PUSH ;
2273+
22862274 task_rq_unlock (rq , p , rf );
2287- stop_one_cpu (cpu_of (rq ), migration_cpu_stop , & arg );
22882275
2276+ if (!stop_pending ) {
2277+ stop_one_cpu_nowait (cpu_of (rq ), migration_cpu_stop ,
2278+ & pending -> arg , & pending -> stop_work );
2279+ }
2280+
2281+ if (flags & SCA_MIGRATE_ENABLE )
2282+ return 0 ;
22892283 } else {
22902284
22912285 if (!is_migration_disabled (p )) {
22922286 if (task_on_rq_queued (p ))
22932287 rq = move_queued_task (rq , rf , p , dest_cpu );
22942288
2295- p -> migration_pending = NULL ;
2296- complete = true;
2289+ if (!pending -> stop_pending ) {
2290+ p -> migration_pending = NULL ;
2291+ complete = true;
2292+ }
22972293 }
22982294 task_rq_unlock (rq , p , rf );
22992295
2300- do_complete :
23012296 if (complete )
23022297 complete_all (& pending -> done );
23032298 }
23042299
23052300 wait_for_completion (& pending -> done );
23062301
23072302 if (refcount_dec_and_test (& pending -> refs ))
2308- wake_up_var (& pending -> refs );
2303+ wake_up_var (& pending -> refs ); /* No UaF, just an address */
23092304
23102305 /*
23112306 * Block the original owner of &pending until all subsequent callers
23122307 * have seen the completion and decremented the refcount
23132308 */
23142309 wait_var_event (& my_pending .refs , !refcount_read (& my_pending .refs ));
23152310
2311+ /* ARGH */
2312+ WARN_ON_ONCE (my_pending .stop_pending );
2313+
23162314 return 0 ;
23172315}
23182316
0 commit comments