block: fix ioprio_get(IOPRIO_WHO_PGRP) vs setuid(2)

do_each_pid_thread(PIDTYPE_PGID) can race with a concurrent
change_pid(PIDTYPE_PGID) that can move the task from one hlist
to another while iterating. Serialize ioprio_get to take
the tasklist_lock in this case, just like it's set counterpart.

Fixes: d69b78ba1de (ioprio: grab rcu_read_lock in sys_ioprio_{set,get}())
Acked-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Link: https://lore.kernel.org/r/20211210182058.43417-1-dave@stgolabs.net
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by Davidlohr Bueso and committed by Jens Axboe e6a59aac a5c24552

+3
+3
block/ioprio.c
··· 220 220 pgrp = task_pgrp(current); 221 221 else 222 222 pgrp = find_vpid(who); 223 + read_lock(&tasklist_lock); 223 224 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { 224 225 tmpio = get_task_ioprio(p); 225 226 if (tmpio < 0) ··· 230 229 else 231 230 ret = ioprio_best(ret, tmpio); 232 231 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 232 + read_unlock(&tasklist_lock); 233 + 233 234 break; 234 235 case IOPRIO_WHO_USER: 235 236 uid = make_kuid(current_user_ns(), who);