| From stable-bounces@linux.kernel.org Fri Aug 11 17:46:20 2006 |
| Message-ID: <44DD24B8.5040307@trash.net> |
| Date: Sat, 12 Aug 2006 02:45:44 +0200 |
| From: Patrick McHardy <kaber@trash.net> |
| To: stable@kernel.org |
| Cc: Adrian Bunk <bunk@stusta.de> |
| Subject: [NETFILTER]: ulog: fix panic on SMP kernels |
| |
| From: Mark Huang <mlhuang@cs.princeton.edu> |
| |
| [NETFILTER]: ulog: fix panic on SMP kernels |
| |
| Fix kernel panic on various SMP machines. The culprit is a null |
| ub->skb in ulog_send(). If ulog_timer() has already been scheduled on |
| one CPU and is spinning on the lock, and ipt_ulog_packet() flushes the |
| queue on another CPU by calling ulog_send() right before it exits, |
| there will be no skbuff when ulog_timer() acquires the lock and calls |
| ulog_send(). Cancelling the timer in ulog_send() doesn't help because |
| it has already been scheduled and is running on the first CPU. |
| |
| Similar problem exists in ebt_ulog.c and nfnetlink_log.c. |
| |
| Signed-off-by: Mark Huang <mlhuang@cs.princeton.edu> |
| Signed-off-by: Patrick McHardy <kaber@trash.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/bridge/netfilter/ebt_ulog.c | 3 +++ |
| net/ipv4/netfilter/ipt_ULOG.c | 5 +++++ |
| net/netfilter/nfnetlink_log.c | 3 +++ |
| 3 files changed, 11 insertions(+) |
| |
| --- linux-2.6.17.9.orig/net/bridge/netfilter/ebt_ulog.c |
| +++ linux-2.6.17.9/net/bridge/netfilter/ebt_ulog.c |
| @@ -75,6 +75,9 @@ static void ulog_send(unsigned int nlgro |
| if (timer_pending(&ub->timer)) |
| del_timer(&ub->timer); |
| |
| + if (!ub->skb) |
| + return; |
| + |
| /* last nlmsg needs NLMSG_DONE */ |
| if (ub->qlen > 1) |
| ub->lastnlh->nlmsg_type = NLMSG_DONE; |
| --- linux-2.6.17.9.orig/net/ipv4/netfilter/ipt_ULOG.c |
| +++ linux-2.6.17.9/net/ipv4/netfilter/ipt_ULOG.c |
| @@ -116,6 +116,11 @@ static void ulog_send(unsigned int nlgro |
| del_timer(&ub->timer); |
| } |
| |
| + if (!ub->skb) { |
| + DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); |
| + return; |
| + } |
| + |
| /* last nlmsg needs NLMSG_DONE */ |
| if (ub->qlen > 1) |
| ub->lastnlh->nlmsg_type = NLMSG_DONE; |
| --- linux-2.6.17.9.orig/net/netfilter/nfnetlink_log.c |
| +++ linux-2.6.17.9/net/netfilter/nfnetlink_log.c |
| @@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *in |
| if (timer_pending(&inst->timer)) |
| del_timer(&inst->timer); |
| |
| + if (!inst->skb) |
| + return 0; |
| + |
| if (inst->qlen > 1) |
| inst->lastnlh->nlmsg_type = NLMSG_DONE; |
| |