On Mon, Mar 08, 2021 at 02:22:10PM +0000, Pavel Begunkov wrote: > On 08/03/2021 14:16, Pavel Begunkov wrote: > > From: "Matthew Wilcox (Oracle)" <willy@xxxxxxxxxxxxx> > > > > You can't call idr_remove() from within a idr_for_each() callback, > > but you can call xa_erase() from an xa_for_each() loop, so switch the > > entire personality_idr from the IDR to the XArray. This manifests as a > > use-after-free as idr_for_each() attempts to walk the rest of the node > > after removing the last entry from it. > > yangerkun, can you test it and similarly take care of buffer idr? FWIW, I did a fairly naive conversion of the personalities IDR, because efficiency really isn't the most important (you don't have a lot of personalities, generally). the buffer_idr seems like it might see a lot more action than the personalities, so you might want to consider something like: +++ b/fs/io_uring.c @@ -8543,7 +8543,8 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx) if (ctx->rings) __io_cqring_overflow_flush(ctx, true, NULL, NULL); xa_for_each(&ctx->personalities, index, creds) - io_unregister_personality(ctx, index); + put_cred(creds); + xa_destroy(&ctx->personalities); mutex_unlock(&ctx->uring_lock); io_kill_timeouts(ctx, NULL, NULL); to be more efficient.