aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-11 10:46:53 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-11 10:46:53 -0400
commite4cb04074c5f5593f98ba2a89a011034f57604e4 (patch)
treebea628194dd7d7481338b954b592ca56477e4429
parentcabe456902e709095ebf1481342ea89910887d60 (diff)
parent0a9c73014415d2a84dac346c1e12169142a6ad37 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: [INET_DIAG]: Fix oops in netlink_rcv_skb [IPv6]: Fix NULL pointer dereference in ip6_flush_pending_frames [NETFILTER]: Fix/improve deadlock condition on module removal netfilter [NETFILTER]: nf_conntrack_ipv4: fix "Frag of proto ..." messages [NET] DOC: Update networking/multiqueue.txt with correct information. [IPV6]: Freeing alive inet6 address [DECNET]: Fix interface address listing regression. [IPV4] devinet: show all addresses assigned to interface [NET]: Do not dereference iov if length is zero [TG3]: Workaround MSI bug on 5714/5780. [Bluetooth] Fix parameter list for event filter command [Bluetooth] Update security filter for Bluetooth 2.1 [Bluetooth] Add compat handling for timestamp structure [Bluetooth] Add missing stat.byte_rx counter modification
-rw-r--r--Documentation/networking/multiqueue.txt10
-rw-r--r--drivers/bluetooth/hci_usb.c5
-rw-r--r--drivers/net/tg3.c13
-rw-r--r--include/linux/netfilter.h5
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/hci_sock.c27
-rw-r--r--net/bridge/netfilter/ebtables.c1
-rw-r--r--net/core/datagram.c3
-rw-r--r--net/decnet/dn_dev.c2
-rw-r--r--net/ipv4/devinet.c2
-rw-r--r--net/ipv4/inet_diag.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c1
-rw-r--r--net/ipv4/netfilter/arp_tables.c1
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c11
-rw-r--r--net/ipv6/ip6_output.c5
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/netfilter/nf_sockopt.c36
19 files changed, 81 insertions, 57 deletions
diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
index 00b60cce22..ea5a42e8f7 100644
--- a/Documentation/networking/multiqueue.txt
+++ b/Documentation/networking/multiqueue.txt
@@ -58,9 +58,13 @@ software, so it's a straight round-robin qdisc. It uses the same syntax and
58classification priomap that sch_prio uses, so it should be intuitive to 58classification priomap that sch_prio uses, so it should be intuitive to
59configure for people who've used sch_prio. 59configure for people who've used sch_prio.
60 60
61The PRIO qdisc naturally plugs into a multiqueue device. If PRIO has been 61In order to utilitize the multiqueue features of the qdiscs, the network
62built with NET_SCH_PRIO_MQ, then upon load, it will make sure the number of 62device layer needs to enable multiple queue support. This can be done by
63bands requested is equal to the number of queues on the hardware. If they 63selecting NETDEVICES_MULTIQUEUE under Drivers.
64
65The PRIO qdisc naturally plugs into a multiqueue device. If
66NETDEVICES_MULTIQUEUE is selected, then on qdisc load, the number of
67bands requested is compared to the number of queues on the hardware. If they
64are equal, it sets a one-to-one mapping up between the queues and bands. If 68are equal, it sets a one-to-one mapping up between the queues and bands. If
65they're not equal, it will not load the qdisc. This is the same behavior 69they're not equal, it will not load the qdisc. This is the same behavior
66for RR. Once the association is made, any skb that is classified will have 70for RR. Once the association is made, any skb that is classified will have
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 59b054810e..98a9cdeaff 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -691,15 +691,18 @@ static void hci_usb_rx_complete(struct urb *urb)
691 urb->iso_frame_desc[i].offset, 691 urb->iso_frame_desc[i].offset,
692 urb->iso_frame_desc[i].actual_length); 692 urb->iso_frame_desc[i].actual_length);
693 693
694 if (!urb->iso_frame_desc[i].status) 694 if (!urb->iso_frame_desc[i].status) {
695 husb->hdev->stat.byte_rx += urb->iso_frame_desc[i].actual_length;
695 hci_recv_fragment(husb->hdev, _urb->type, 696 hci_recv_fragment(husb->hdev, _urb->type,
696 urb->transfer_buffer + urb->iso_frame_desc[i].offset, 697 urb->transfer_buffer + urb->iso_frame_desc[i].offset,
697 urb->iso_frame_desc[i].actual_length); 698 urb->iso_frame_desc[i].actual_length);
699 }
698 } 700 }
699#else 701#else
700 ; 702 ;
701#endif 703#endif
702 } else { 704 } else {
705 husb->hdev->stat.byte_rx += count;
703 err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count); 706 err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count);
704 if (err < 0) { 707 if (err < 0) {
705 BT_ERR("%s corrupted packet: type %d count %d", 708 BT_ERR("%s corrupted packet: type %d count %d",
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 58740428dd..9034a05734 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
64 64
65#define DRV_MODULE_NAME "tg3" 65#define DRV_MODULE_NAME "tg3"
66#define PFX DRV_MODULE_NAME ": " 66#define PFX DRV_MODULE_NAME ": "
67#define DRV_MODULE_VERSION "3.80" 67#define DRV_MODULE_VERSION "3.81"
68#define DRV_MODULE_RELDATE "August 2, 2007" 68#define DRV_MODULE_RELDATE "September 5, 2007"
69 69
70#define TG3_DEF_MAC_MODE 0 70#define TG3_DEF_MAC_MODE 0
71#define TG3_DEF_RX_MODE 0 71#define TG3_DEF_RX_MODE 0
@@ -7127,6 +7127,10 @@ static int tg3_open(struct net_device *dev)
7127 } else if (pci_enable_msi(tp->pdev) == 0) { 7127 } else if (pci_enable_msi(tp->pdev) == 0) {
7128 u32 msi_mode; 7128 u32 msi_mode;
7129 7129
7130 /* Hardware bug - MSI won't work if INTX disabled. */
7131 if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
7132 pci_intx(tp->pdev, 1);
7133
7130 msi_mode = tr32(MSGINT_MODE); 7134 msi_mode = tr32(MSGINT_MODE);
7131 tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); 7135 tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
7132 tp->tg3_flags2 |= TG3_FLG2_USING_MSI; 7136 tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
@@ -12172,6 +12176,11 @@ static int tg3_resume(struct pci_dev *pdev)
12172 if (err) 12176 if (err)
12173 return err; 12177 return err;
12174 12178
12179 /* Hardware bug - MSI won't work if INTX disabled. */
12180 if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
12181 (tp->tg3_flags2 & TG3_FLG2_USING_MSI))
12182 pci_intx(tp->pdev, 1);
12183
12175 netif_device_attach(dev); 12184 netif_device_attach(dev);
12176 12185
12177 tg3_full_lock(tp, 0); 12186 tg3_full_lock(tp, 0);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 0eed0b7ab2..1dd075eda5 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -88,9 +88,8 @@ struct nf_sockopt_ops
88 int (*compat_get)(struct sock *sk, int optval, 88 int (*compat_get)(struct sock *sk, int optval,
89 void __user *user, int *len); 89 void __user *user, int *len);
90 90
91 /* Number of users inside set() or get(). */ 91 /* Use the module struct to lock set/get code in place */
92 unsigned int use; 92 struct module *owner;
93 struct task_struct *cleanup_task;
94}; 93};
95 94
96/* Each queued (to userspace) skbuff has one of these. */ 95/* Each queued (to userspace) skbuff has one of these. */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 63caa41494..18e3afc964 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -183,6 +183,7 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
183{ 183{
184 struct sk_buff *skb; 184 struct sk_buff *skb;
185 __le16 param; 185 __le16 param;
186 __u8 flt_type;
186 187
187 BT_DBG("%s %ld", hdev->name, opt); 188 BT_DBG("%s %ld", hdev->name, opt);
188 189
@@ -233,11 +234,8 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
233 /* Optional initialization */ 234 /* Optional initialization */
234 235
235 /* Clear Event Filters */ 236 /* Clear Event Filters */
236 { 237 flt_type = HCI_FLT_CLEAR_ALL;
237 struct hci_cp_set_event_flt cp; 238 hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, 1, &flt_type);
238 cp.flt_type = HCI_FLT_CLEAR_ALL;
239 hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, sizeof(cp), &cp);
240 }
241 239
242 /* Page timeout ~20 secs */ 240 /* Page timeout ~20 secs */
243 param = cpu_to_le16(0x8000); 241 param = cpu_to_le16(0x8000);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1dae3dfc66..d16ca8e537 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -37,6 +37,7 @@
37#include <linux/skbuff.h> 37#include <linux/skbuff.h>
38#include <linux/workqueue.h> 38#include <linux/workqueue.h>
39#include <linux/interrupt.h> 39#include <linux/interrupt.h>
40#include <linux/compat.h>
40#include <linux/socket.h> 41#include <linux/socket.h>
41#include <linux/ioctl.h> 42#include <linux/ioctl.h>
42#include <net/sock.h> 43#include <net/sock.h>
@@ -70,15 +71,15 @@ static struct hci_sec_filter hci_sec_filter = {
70 { 71 {
71 { 0x0 }, 72 { 0x0 },
72 /* OGF_LINK_CTL */ 73 /* OGF_LINK_CTL */
73 { 0xbe000006, 0x00000001, 0x000000, 0x00 }, 74 { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
74 /* OGF_LINK_POLICY */ 75 /* OGF_LINK_POLICY */
75 { 0x00005200, 0x00000000, 0x000000, 0x00 }, 76 { 0x00005200, 0x00000000, 0x00000000, 0x00 },
76 /* OGF_HOST_CTL */ 77 /* OGF_HOST_CTL */
77 { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 }, 78 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
78 /* OGF_INFO_PARAM */ 79 /* OGF_INFO_PARAM */
79 { 0x000002be, 0x00000000, 0x000000, 0x00 }, 80 { 0x000002be, 0x00000000, 0x00000000, 0x00 },
80 /* OGF_STATUS_PARAM */ 81 /* OGF_STATUS_PARAM */
81 { 0x000000ea, 0x00000000, 0x000000, 0x00 } 82 { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
82 } 83 }
83}; 84};
84 85
@@ -342,9 +343,23 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
342 343
343 if (mask & HCI_CMSG_TSTAMP) { 344 if (mask & HCI_CMSG_TSTAMP) {
344 struct timeval tv; 345 struct timeval tv;
346 void *data;
347 int len;
345 348
346 skb_get_timestamp(skb, &tv); 349 skb_get_timestamp(skb, &tv);
347 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(tv), &tv); 350
351 if (msg->msg_flags & MSG_CMSG_COMPAT) {
352 struct compat_timeval ctv;
353 ctv.tv_sec = tv.tv_sec;
354 ctv.tv_usec = tv.tv_usec;
355 data = &ctv;
356 len = sizeof(ctv);
357 } else {
358 data = &tv;
359 len = sizeof(tv);
360 }
361
362 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
348 } 363 }
349} 364}
350 365
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 4169a2a89a..6018d0e519 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1513,6 +1513,7 @@ static struct nf_sockopt_ops ebt_sockopts =
1513 .get_optmin = EBT_BASE_CTL, 1513 .get_optmin = EBT_BASE_CTL,
1514 .get_optmax = EBT_SO_GET_MAX + 1, 1514 .get_optmax = EBT_SO_GET_MAX + 1,
1515 .get = do_ebt_get_ctl, 1515 .get = do_ebt_get_ctl,
1516 .owner = THIS_MODULE,
1516}; 1517};
1517 1518
1518static int __init ebtables_init(void) 1519static int __init ebtables_init(void)
diff --git a/net/core/datagram.c b/net/core/datagram.c
index cb056f4761..029b93e246 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -450,6 +450,9 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
450 __wsum csum; 450 __wsum csum;
451 int chunk = skb->len - hlen; 451 int chunk = skb->len - hlen;
452 452
453 if (!chunk)
454 return 0;
455
453 /* Skip filled elements. 456 /* Skip filled elements.
454 * Pretty silly, look at memcpy_toiovec, though 8) 457 * Pretty silly, look at memcpy_toiovec, though 8)
455 */ 458 */
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index fa6604fcf0..8def68209e 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -814,7 +814,7 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
814 for (ifa = dn_db->ifa_list, dn_idx = 0; ifa; 814 for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
815 ifa = ifa->ifa_next, dn_idx++) { 815 ifa = ifa->ifa_next, dn_idx++) {
816 if (dn_idx < skip_naddr) 816 if (dn_idx < skip_naddr)
817 goto cont; 817 continue;
818 818
819 if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, 819 if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
820 cb->nlh->nlmsg_seq, RTM_NEWADDR, 820 cb->nlh->nlmsg_seq, RTM_NEWADDR,
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5b77bdaa57..5dbe5803b7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1193,7 +1193,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1193 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; 1193 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
1194 ifa = ifa->ifa_next, ip_idx++) { 1194 ifa = ifa->ifa_next, ip_idx++) {
1195 if (ip_idx < s_ip_idx) 1195 if (ip_idx < s_ip_idx)
1196 goto cont; 1196 continue;
1197 if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, 1197 if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
1198 cb->nlh->nlmsg_seq, 1198 cb->nlh->nlmsg_seq,
1199 RTM_NEWADDR, NLM_F_MULTI) <= 0) 1199 RTM_NEWADDR, NLM_F_MULTI) <= 0)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index dbeacd8b0f..def007ec1d 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -836,12 +836,16 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
836 return inet_diag_get_exact(skb, nlh); 836 return inet_diag_get_exact(skb, nlh);
837} 837}
838 838
839static DEFINE_MUTEX(inet_diag_mutex);
840
839static void inet_diag_rcv(struct sock *sk, int len) 841static void inet_diag_rcv(struct sock *sk, int len)
840{ 842{
841 unsigned int qlen = 0; 843 unsigned int qlen = 0;
842 844
843 do { 845 do {
846 mutex_lock(&inet_diag_mutex);
844 netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg); 847 netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg);
848 mutex_unlock(&inet_diag_mutex);
845 } while (qlen); 849 } while (qlen);
846} 850}
847 851
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 902fd578aa..f656d41d8d 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -2339,6 +2339,7 @@ static struct nf_sockopt_ops ip_vs_sockopts = {
2339 .get_optmin = IP_VS_BASE_CTL, 2339 .get_optmin = IP_VS_BASE_CTL,
2340 .get_optmax = IP_VS_SO_GET_MAX+1, 2340 .get_optmax = IP_VS_SO_GET_MAX+1,
2341 .get = do_ip_vs_get_ctl, 2341 .get = do_ip_vs_get_ctl,
2342 .owner = THIS_MODULE,
2342}; 2343};
2343 2344
2344 2345
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index d1149aba93..29114a9ccd 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1161,6 +1161,7 @@ static struct nf_sockopt_ops arpt_sockopts = {
1161 .get_optmin = ARPT_BASE_CTL, 1161 .get_optmin = ARPT_BASE_CTL,
1162 .get_optmax = ARPT_SO_GET_MAX+1, 1162 .get_optmax = ARPT_SO_GET_MAX+1,
1163 .get = do_arpt_get_ctl, 1163 .get = do_arpt_get_ctl,
1164 .owner = THIS_MODULE,
1164}; 1165};
1165 1166
1166static int __init arp_tables_init(void) 1167static int __init arp_tables_init(void)
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e1b402c6b8..6486894f45 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2296,6 +2296,7 @@ static struct nf_sockopt_ops ipt_sockopts = {
2296#ifdef CONFIG_COMPAT 2296#ifdef CONFIG_COMPAT
2297 .compat_get = compat_do_ipt_get_ctl, 2297 .compat_get = compat_do_ipt_get_ctl,
2298#endif 2298#endif
2299 .owner = THIS_MODULE,
2299}; 2300};
2300 2301
2301static struct xt_match icmp_matchstruct __read_mostly = { 2302static struct xt_match icmp_matchstruct __read_mostly = {
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index d9b5177989..f813e02aab 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -87,14 +87,10 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
87 if (iph == NULL) 87 if (iph == NULL)
88 return -NF_DROP; 88 return -NF_DROP;
89 89
90 /* Never happen */ 90 /* Conntrack defragments packets, we might still see fragments
91 if (iph->frag_off & htons(IP_OFFSET)) { 91 * inside ICMP packets though. */
92 if (net_ratelimit()) { 92 if (iph->frag_off & htons(IP_OFFSET))
93 printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n",
94 iph->protocol);
95 }
96 return -NF_DROP; 93 return -NF_DROP;
97 }
98 94
99 *dataoff = nhoff + (iph->ihl << 2); 95 *dataoff = nhoff + (iph->ihl << 2);
100 *protonum = iph->protocol; 96 *protonum = iph->protocol;
@@ -403,6 +399,7 @@ static struct nf_sockopt_ops so_getorigdst = {
403 .get_optmin = SO_ORIGINAL_DST, 399 .get_optmin = SO_ORIGINAL_DST,
404 .get_optmax = SO_ORIGINAL_DST+1, 400 .get_optmax = SO_ORIGINAL_DST+1,
405 .get = &getorigdst, 401 .get = &getorigdst,
402 .owner = THIS_MODULE,
406}; 403};
407 404
408struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { 405struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5dead399fe..26de3c0ea3 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1427,8 +1427,9 @@ void ip6_flush_pending_frames(struct sock *sk)
1427 struct sk_buff *skb; 1427 struct sk_buff *skb;
1428 1428
1429 while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { 1429 while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
1430 IP6_INC_STATS(ip6_dst_idev(skb->dst), 1430 if (skb->dst)
1431 IPSTATS_MIB_OUTDISCARDS); 1431 IP6_INC_STATS(ip6_dst_idev(skb->dst),
1432 IPSTATS_MIB_OUTDISCARDS);
1432 kfree_skb(skb); 1433 kfree_skb(skb);
1433 } 1434 }
1434 1435
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0358e6066a..73a894a215 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -736,7 +736,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
736 * so fail our DAD process 736 * so fail our DAD process
737 */ 737 */
738 addrconf_dad_failure(ifp); 738 addrconf_dad_failure(ifp);
739 goto out; 739 return;
740 } else { 740 } else {
741 /* 741 /*
742 * This is not a dad solicitation. 742 * This is not a dad solicitation.
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index aeda617246..cd9df02bb8 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1462,6 +1462,7 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1462 .get_optmin = IP6T_BASE_CTL, 1462 .get_optmin = IP6T_BASE_CTL,
1463 .get_optmax = IP6T_SO_GET_MAX+1, 1463 .get_optmax = IP6T_SO_GET_MAX+1,
1464 .get = do_ip6t_get_ctl, 1464 .get = do_ip6t_get_ctl,
1465 .owner = THIS_MODULE,
1465}; 1466};
1466 1467
1467static struct xt_match icmp6_matchstruct __read_mostly = { 1468static struct xt_match icmp6_matchstruct __read_mostly = {
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 8b8ece7503..e32761ce26 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -55,18 +55,7 @@ EXPORT_SYMBOL(nf_register_sockopt);
55 55
56void nf_unregister_sockopt(struct nf_sockopt_ops *reg) 56void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
57{ 57{
58 /* No point being interruptible: we're probably in cleanup_module() */
59 restart:
60 mutex_lock(&nf_sockopt_mutex); 58 mutex_lock(&nf_sockopt_mutex);
61 if (reg->use != 0) {
62 /* To be woken by nf_sockopt call... */
63 /* FIXME: Stuart Young's name appears gratuitously. */
64 set_current_state(TASK_UNINTERRUPTIBLE);
65 reg->cleanup_task = current;
66 mutex_unlock(&nf_sockopt_mutex);
67 schedule();
68 goto restart;
69 }
70 list_del(&reg->list); 59 list_del(&reg->list);
71 mutex_unlock(&nf_sockopt_mutex); 60 mutex_unlock(&nf_sockopt_mutex);
72} 61}
@@ -86,10 +75,11 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
86 list_for_each(i, &nf_sockopts) { 75 list_for_each(i, &nf_sockopts) {
87 ops = (struct nf_sockopt_ops *)i; 76 ops = (struct nf_sockopt_ops *)i;
88 if (ops->pf == pf) { 77 if (ops->pf == pf) {
78 if (!try_module_get(ops->owner))
79 goto out_nosup;
89 if (get) { 80 if (get) {
90 if (val >= ops->get_optmin 81 if (val >= ops->get_optmin
91 && val < ops->get_optmax) { 82 && val < ops->get_optmax) {
92 ops->use++;
93 mutex_unlock(&nf_sockopt_mutex); 83 mutex_unlock(&nf_sockopt_mutex);
94 ret = ops->get(sk, val, opt, len); 84 ret = ops->get(sk, val, opt, len);
95 goto out; 85 goto out;
@@ -97,23 +87,20 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
97 } else { 87 } else {
98 if (val >= ops->set_optmin 88 if (val >= ops->set_optmin
99 && val < ops->set_optmax) { 89 && val < ops->set_optmax) {
100 ops->use++;
101 mutex_unlock(&nf_sockopt_mutex); 90 mutex_unlock(&nf_sockopt_mutex);
102 ret = ops->set(sk, val, opt, *len); 91 ret = ops->set(sk, val, opt, *len);
103 goto out; 92 goto out;
104 } 93 }
105 } 94 }
95 module_put(ops->owner);
106 } 96 }
107 } 97 }
98 out_nosup:
108 mutex_unlock(&nf_sockopt_mutex); 99 mutex_unlock(&nf_sockopt_mutex);
109 return -ENOPROTOOPT; 100 return -ENOPROTOOPT;
110 101
111 out: 102 out:
112 mutex_lock(&nf_sockopt_mutex); 103 module_put(ops->owner);
113 ops->use--;
114 if (ops->cleanup_task)
115 wake_up_process(ops->cleanup_task);
116 mutex_unlock(&nf_sockopt_mutex);
117 return ret; 104 return ret;
118} 105}
119 106
@@ -144,10 +131,12 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
144 list_for_each(i, &nf_sockopts) { 131 list_for_each(i, &nf_sockopts) {
145 ops = (struct nf_sockopt_ops *)i; 132 ops = (struct nf_sockopt_ops *)i;
146 if (ops->pf == pf) { 133 if (ops->pf == pf) {
134 if (!try_module_get(ops->owner))
135 goto out_nosup;
136
147 if (get) { 137 if (get) {
148 if (val >= ops->get_optmin 138 if (val >= ops->get_optmin
149 && val < ops->get_optmax) { 139 && val < ops->get_optmax) {
150 ops->use++;
151 mutex_unlock(&nf_sockopt_mutex); 140 mutex_unlock(&nf_sockopt_mutex);
152 if (ops->compat_get) 141 if (ops->compat_get)
153 ret = ops->compat_get(sk, 142 ret = ops->compat_get(sk,
@@ -160,7 +149,6 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
160 } else { 149 } else {
161 if (val >= ops->set_optmin 150 if (val >= ops->set_optmin
162 && val < ops->set_optmax) { 151 && val < ops->set_optmax) {
163 ops->use++;
164 mutex_unlock(&nf_sockopt_mutex); 152 mutex_unlock(&nf_sockopt_mutex);
165 if (ops->compat_set) 153 if (ops->compat_set)
166 ret = ops->compat_set(sk, 154 ret = ops->compat_set(sk,
@@ -171,17 +159,15 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
171 goto out; 159 goto out;
172 } 160 }
173 } 161 }
162 module_put(ops->owner);
174 } 163 }
175 } 164 }
165 out_nosup:
176 mutex_unlock(&nf_sockopt_mutex); 166 mutex_unlock(&nf_sockopt_mutex);
177 return -ENOPROTOOPT; 167 return -ENOPROTOOPT;
178 168
179 out: 169 out:
180 mutex_lock(&nf_sockopt_mutex); 170 module_put(ops->owner);
181 ops->use--;
182 if (ops->cleanup_task)
183 wake_up_process(ops->cleanup_task);
184 mutex_unlock(&nf_sockopt_mutex);
185 return ret; 171 return ret;
186} 172}
187 173