diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-11 10:46:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-11 10:46:53 -0400 |
commit | e4cb04074c5f5593f98ba2a89a011034f57604e4 (patch) | |
tree | bea628194dd7d7481338b954b592ca56477e4429 | |
parent | cabe456902e709095ebf1481342ea89910887d60 (diff) | |
parent | 0a9c73014415d2a84dac346c1e12169142a6ad37 (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.txt | 10 | ||||
-rw-r--r-- | drivers/bluetooth/hci_usb.c | 5 | ||||
-rw-r--r-- | drivers/net/tg3.c | 13 | ||||
-rw-r--r-- | include/linux/netfilter.h | 5 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 8 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 27 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 1 | ||||
-rw-r--r-- | net/core/datagram.c | 3 | ||||
-rw-r--r-- | net/decnet/dn_dev.c | 2 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 2 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_ctl.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 5 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_sockopt.c | 36 |
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 | |||
58 | classification priomap that sch_prio uses, so it should be intuitive to | 58 | classification priomap that sch_prio uses, so it should be intuitive to |
59 | configure for people who've used sch_prio. | 59 | configure for people who've used sch_prio. |
60 | 60 | ||
61 | The PRIO qdisc naturally plugs into a multiqueue device. If PRIO has been | 61 | In order to utilitize the multiqueue features of the qdiscs, the network |
62 | built with NET_SCH_PRIO_MQ, then upon load, it will make sure the number of | 62 | device layer needs to enable multiple queue support. This can be done by |
63 | bands requested is equal to the number of queues on the hardware. If they | 63 | selecting NETDEVICES_MULTIQUEUE under Drivers. |
64 | |||
65 | The PRIO qdisc naturally plugs into a multiqueue device. If | ||
66 | NETDEVICES_MULTIQUEUE is selected, then on qdisc load, the number of | ||
67 | bands requested is compared to the number of queues on the hardware. If they | ||
64 | are equal, it sets a one-to-one mapping up between the queues and bands. If | 68 | are equal, it sets a one-to-one mapping up between the queues and bands. If |
65 | they're not equal, it will not load the qdisc. This is the same behavior | 69 | they're not equal, it will not load the qdisc. This is the same behavior |
66 | for RR. Once the association is made, any skb that is classified will have | 70 | for 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 | ||
1518 | static int __init ebtables_init(void) | 1519 | static 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 | ||
839 | static DEFINE_MUTEX(inet_diag_mutex); | ||
840 | |||
839 | static void inet_diag_rcv(struct sock *sk, int len) | 841 | static 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 | ||
1166 | static int __init arp_tables_init(void) | 1167 | static 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 | ||
2301 | static struct xt_match icmp_matchstruct __read_mostly = { | 2302 | static 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 | ||
408 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { | 405 | struct 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 | ||
1467 | static struct xt_match icmp6_matchstruct __read_mostly = { | 1468 | static 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 | ||
56 | void nf_unregister_sockopt(struct nf_sockopt_ops *reg) | 56 | void 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(®->list); | 59 | list_del(®->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 | ||