Re: af_packet: use after free in prb_retire_rx_blk_timer_expired

From: Willem de Bruijn
Date: Tue Apr 11 2017 - 19:23:25 EST


On Mon, Apr 10, 2017 at 3:23 PM, Dave Jones <davej@xxxxxxxxxxxxxxxxx> wrote:
> On Mon, Apr 10, 2017 at 07:03:30PM +0000, alexander.levin@xxxxxxxxxxx wrote:
> > Hi all,
> >
> > I seem to be hitting this use-after-free on a -next kernel using trinity:
> >
> > [ 531.036054] BUG: KASAN: use-after-free in prb_retire_rx_blk_timer_expired (net/packet/af_packet.c:688)

The retire_blk_timer is called after the pg_vec struct for this ring
was freed. This should not happen. packet_set_ring stops the timer
with del_timer_sync when tearing down the ring before freeing that
struct:

if (closing && (po->tp_version > TPACKET_V2)) {
/* Because we don't support block-based V3 on tx-ring */
if (!tx_ring)
prb_shutdown_retire_blk_timer(po, rb_queue);
}

if (pg_vec)
free_pg_vec(pg_vec, order, req->tp_block_nr);

This is a similar race to the use-after-free fixed by 84ac7260236a
("packet: fix race condition in packet_set_ring"). The previous race
was triggered by a call to setsockopt PACKET_VERSION changing
tp_version while the ring is active. It is not immediately obvious
what is the cause now. I suppose trinity does not give a trace of such
system calls on this file descriptor? That would be helpful.

The bug report shows both a timer firing after the packet_set_ring
call that freed the pg_vec, and later a CONFIG_DEBUG_OBJECTS_FREE
warning that the timer is still active when the socket is closed on
release of the last file descriptor.