Re: [PATCH] fix sighand use after free

From: Oleg Nesterov
Date: Wed Aug 13 2014 - 12:21:38 EST


On 08/13, Rik van Riel wrote:
>
> On 08/13/2014 11:58 AM, Oleg Nesterov wrote:
> > On 08/13, Rik van Riel wrote:
> >>
> >> @@ -1017,7 +1017,7 @@ void __cleanup_sighand(struct sighand_struct *sighand)
> >> {
> >> if (atomic_dec_and_test(&sighand->count)) {
> >> signalfd_cleanup(sighand);
> >> - kmem_cache_free(sighand_cachep, sighand);
> >> + rcu_free(sighand_cachep, sighand);
> >
> > Please note that sighand_cachep is SLAB_DESTROY_BY_RCU.
>
> SLAB_DESTROY_BY_RCU means that the slab page is not given
> back to the system until after the RCU grace period has
> expired.
>
> However, the objects inside the slab can still be reused
> immediately!

Yes. This is fine. This memory won't be returned to system before rcu
gp pass, and this memory is still "struct sighand_struct" with the
properly initialized ->siglock (note the sighand_ctor()).

> In the case of the sighand struct, we have this possible race:
>
> thread A thread B thread C
>
> gets task A->sighand
> kmem_cache_free sighand
> re-alloc sighand
> spin_lock sighand
> spin_lock_init sighand
^^^^^^^^^^^^^^^^^^^^^^
see below,

> spin_unlock sighand
>
> Now task C has a sighand which can never be locked.

No, please see above. And that is why lock_task_sighand() (which in
turn needs the comment and cleanup, I already have a patch) re-checks
task-sighand with ->siglock.

> > Hmm. and what is rcu_free() ?
>
> Ugh, that should have been kfree_rcu of course, with
> appropriate rcu space in the struct.

kfree_rcu() can't work in this case, __rcu_reclaim() does kfree() but
we need kmem_cache_free().

Oleg.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/