Skip to content

Commit

Permalink
caif: Bugfix list_del_rcu race in cfmuxl_ctrlcmd.
Browse files Browse the repository at this point in the history
Always use cfmuxl_remove_uplayer when removing a up-layer.
cfmuxl_ctrlcmd() can be called independently and in parallel with
cfmuxl_remove_uplayer(). The race between them could cause list_del_rcu
to be called on a node which has been already taken out from the list.
That lead to a (rare) crash on accessing poisoned node->prev inside
list_del_rcu.

This fix ensures that deletion are done holding the same lock.

Reported-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
sjur.brandeland@stericsson.com authored and David S. Miller committed Feb 2, 2012
1 parent c31c151 commit b01377a
Showing 1 changed file with 3 additions and 9 deletions.
12 changes: 3 additions & 9 deletions net/caif/cfmuxl.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
{
struct cfmuxl *muxl = container_obj(layr);
struct cflayer *layer;
int idx;

rcu_read_lock();
list_for_each_entry_rcu(layer, &muxl->srvl_list, node) {
Expand All @@ -257,14 +256,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,

if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||
ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) &&
layer->id != 0) {

idx = layer->id % UP_CACHE_SIZE;
spin_lock_bh(&muxl->receive_lock);
RCU_INIT_POINTER(muxl->up_cache[idx], NULL);
list_del_rcu(&layer->node);
spin_unlock_bh(&muxl->receive_lock);
}
layer->id != 0)
cfmuxl_remove_uplayer(layr, layer->id);

/* NOTE: ctrlcmd is not allowed to block */
layer->ctrlcmd(layer, ctrl, phyid);
}
Expand Down

0 comments on commit b01377a

Please sign in to comment.