Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj

We should acquire the ct->lock before accessing or modifying the
nf_ct_seqadj, as another CPU may modify the nf_ct_seqadj at the same
time during its packet proccessing.

Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Liping Zhang and committed by
Pablo Neira Ayuso
64f3967c 53b56da8

+15 -6
+15 -6
net/netfilter/nf_conntrack_netlink.c
··· 417 417 return -1; 418 418 } 419 419 420 - static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, 421 - const struct nf_conn *ct) 420 + static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct) 422 421 { 423 422 struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); 424 423 struct nf_ct_seqadj *seq; ··· 425 426 if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj) 426 427 return 0; 427 428 429 + spin_lock_bh(&ct->lock); 428 430 seq = &seqadj->seq[IP_CT_DIR_ORIGINAL]; 429 431 if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1) 430 - return -1; 432 + goto err; 431 433 432 434 seq = &seqadj->seq[IP_CT_DIR_REPLY]; 433 435 if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1) 434 - return -1; 436 + goto err; 435 437 438 + spin_unlock_bh(&ct->lock); 436 439 return 0; 440 + err: 441 + spin_unlock_bh(&ct->lock); 442 + return -1; 437 443 } 438 444 439 445 static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) ··· 1641 1637 if (!seqadj) 1642 1638 return 0; 1643 1639 1640 + spin_lock_bh(&ct->lock); 1644 1641 if (cda[CTA_SEQ_ADJ_ORIG]) { 1645 1642 ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL], 1646 1643 cda[CTA_SEQ_ADJ_ORIG]); 1647 1644 if (ret < 0) 1648 - return ret; 1645 + goto err; 1649 1646 1650 1647 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 1651 1648 } ··· 1655 1650 ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY], 1656 1651 cda[CTA_SEQ_ADJ_REPLY]); 1657 1652 if (ret < 0) 1658 - return ret; 1653 + goto err; 1659 1654 1660 1655 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 1661 1656 } 1662 1657 1658 + spin_unlock_bh(&ct->lock); 1663 1659 return 0; 1660 + err: 1661 + spin_unlock_bh(&ct->lock); 1662 + return ret; 1664 1663 } 1665 1664 1666 1665 static int