From f2a89004da23a5ed2d78ac5550ccda5b714fe7d0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 12 Dec 2007 10:34:29 -0800 Subject: [NETFILTER]: ctnetlink: set expected bit for related conntracks This patch is a fix. It sets IPS_EXPECTED for related conntracks. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9be1826e6cd..7d231243754 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1024,8 +1024,10 @@ ctnetlink_create_conntrack(struct nlattr *cda[], } /* setup master conntrack: this is a confirmed expectation */ - if (master_ct) + if (master_ct) { + __set_bit(IPS_EXPECTED_BIT, &ct->status); ct->master = master_ct; + } add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); -- cgit v1.2.3 From a18aa31b7774d8b36048e256a02d9d689533fc96 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 12 Dec 2007 10:35:16 -0800 Subject: [NETFILTER]: ip_tables: fix compat copy race When copying entries to user, the kernel makes two passes through the data, first copying all the entries, then fixing up names and counters. On the second pass it copies the kernel and match data from userspace to the kernel again to find the corresponding structures, expecting that kernel pointers contained in the data are still valid. This is obviously broken, fix by avoiding the second pass completely and fixing names and counters while dumping the ruleset, using the kernel-internal data structures. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_tables.c | 57 +++++++++--------------------------------- net/netfilter/x_tables.c | 8 ++++-- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4b10b98640a..b9b189c2620 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1492,8 +1492,10 @@ static inline int compat_copy_match_to_user(struct ipt_entry_match *m, return xt_compat_match_to_user(m, dstptr, size); } -static int compat_copy_entry_to_user(struct ipt_entry *e, - void __user **dstptr, compat_uint_t *size) +static int +compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, + compat_uint_t *size, struct xt_counters *counters, + unsigned int *i) { struct ipt_entry_target *t; struct compat_ipt_entry __user *ce; @@ -1507,6 +1509,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, if (copy_to_user(ce, e, sizeof(struct ipt_entry))) goto out; + if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) + goto out; + *dstptr += sizeof(struct compat_ipt_entry); ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size); target_offset = e->target_offset - (origsize - *size); @@ -1522,6 +1527,8 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, goto out; if (put_user(next_offset, &ce->next_offset)) goto out; + + (*i)++; return 0; out: return ret; @@ -1937,14 +1944,13 @@ struct compat_ipt_get_entries static int compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, void __user *userptr) { - unsigned int off, num; - struct compat_ipt_entry e; struct xt_counters *counters; struct xt_table_info *private = table->private; void __user *pos; unsigned int size; int ret = 0; void *loc_cpu_entry; + unsigned int i = 0; counters = alloc_counters(table); if (IS_ERR(counters)) @@ -1958,48 +1964,9 @@ static int compat_copy_entries_to_user(unsigned int total_size, pos = userptr; size = total_size; ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, - compat_copy_entry_to_user, &pos, &size); - if (ret) - goto free_counters; - - /* ... then go back and fix counters and names */ - for (off = 0, num = 0; off < size; off += e.next_offset, num++) { - unsigned int i; - struct ipt_entry_match m; - struct ipt_entry_target t; + compat_copy_entry_to_user, + &pos, &size, counters, &i); - ret = -EFAULT; - if (copy_from_user(&e, userptr + off, - sizeof(struct compat_ipt_entry))) - goto free_counters; - if (copy_to_user(userptr + off + - offsetof(struct compat_ipt_entry, counters), - &counters[num], sizeof(counters[num]))) - goto free_counters; - - for (i = sizeof(struct compat_ipt_entry); - i < e.target_offset; i += m.u.match_size) { - if (copy_from_user(&m, userptr + off + i, - sizeof(struct ipt_entry_match))) - goto free_counters; - if (copy_to_user(userptr + off + i + - offsetof(struct ipt_entry_match, u.user.name), - m.u.kernel.match->name, - strlen(m.u.kernel.match->name) + 1)) - goto free_counters; - } - - if (copy_from_user(&t, userptr + off + e.target_offset, - sizeof(struct ipt_entry_target))) - goto free_counters; - if (copy_to_user(userptr + off + e.target_offset + - offsetof(struct ipt_entry_target, u.user.name), - t.u.kernel.target->name, - strlen(t.u.kernel.target->name) + 1)) - goto free_counters; - } - ret = 0; -free_counters: vfree(counters); return ret; } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d9a3bded0d0..b6160e41eb1 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -377,7 +377,9 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, u_int16_t msize = m->u.user.match_size - off; if (copy_to_user(cm, m, sizeof(*cm)) || - put_user(msize, &cm->u.user.match_size)) + put_user(msize, &cm->u.user.match_size) || + copy_to_user(cm->u.user.name, m->u.kernel.match->name, + strlen(m->u.kernel.match->name) + 1)) return -EFAULT; if (match->compat_to_user) { @@ -468,7 +470,9 @@ int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr, u_int16_t tsize = t->u.user.target_size - off; if (copy_to_user(ct, t, sizeof(*ct)) || - put_user(tsize, &ct->u.user.target_size)) + put_user(tsize, &ct->u.user.target_size) || + copy_to_user(ct->u.user.name, t->u.kernel.target->name, + strlen(t->u.kernel.target->name) + 1)) return -EFAULT; if (target->compat_to_user) { -- cgit v1.2.3 From 9ab4c954ce2b2b3c485bee7e425fda05946893be Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 12 Dec 2007 11:10:16 -0800 Subject: [XFRM]: Display the audited SPI value in host byte order. Currently the IPsec protocol SPI values are written to the audit log in network byte order which is different from almost all other values which are recorded in host byte order. This patch corrects this inconsistency by writing the SPI values to the audit record in host byte order. Signed-off-by: Paul Moore Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index cf43c49eab3..1af522bf12c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2028,6 +2028,7 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result, u32 auid, u32 sid) { struct audit_buffer *audit_buf; + u32 spi; extern int audit_enabled; if (audit_enabled == 0) @@ -2037,8 +2038,8 @@ xfrm_audit_state_add(struct xfrm_state *x, int result, u32 auid, u32 sid) return; audit_log_format(audit_buf, " op=SAD-add res=%u",result); xfrm_audit_common_stateinfo(x, audit_buf); - audit_log_format(audit_buf, " spi=%lu(0x%lx)", - (unsigned long)x->id.spi, (unsigned long)x->id.spi); + spi = ntohl(x->id.spi); + audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi); audit_log_end(audit_buf); } EXPORT_SYMBOL_GPL(xfrm_audit_state_add); @@ -2047,6 +2048,7 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 sid) { struct audit_buffer *audit_buf; + u32 spi; extern int audit_enabled; if (audit_enabled == 0) @@ -2056,8 +2058,8 @@ xfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 sid) return; audit_log_format(audit_buf, " op=SAD-delete res=%u",result); xfrm_audit_common_stateinfo(x, audit_buf); - audit_log_format(audit_buf, " spi=%lu(0x%lx)", - (unsigned long)x->id.spi, (unsigned long)x->id.spi); + spi = ntohl(x->id.spi); + audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi); audit_log_end(audit_buf); } EXPORT_SYMBOL_GPL(xfrm_audit_state_delete); -- cgit v1.2.3 From cbebc51f7b77d26ec23145d6ef22ac2b209f7955 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 12 Dec 2007 11:11:28 -0800 Subject: [NETFILTER]: xt_hashlimit should use time_after_eq() In order to avoid jiffies wraparound and its effect, special care must be taken when doing comparisons ... Signed-off-by: Eric Dumazet Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/xt_hashlimit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 19103678bf2..2ef44d8560c 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -240,7 +240,7 @@ static bool select_all(const struct xt_hashlimit_htable *ht, static bool select_gc(const struct xt_hashlimit_htable *ht, const struct dsthash_ent *he) { - return jiffies >= he->expires; + return time_after_eq(jiffies, he->expires); } static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, -- cgit v1.2.3 From 98eb5683fb94c458b3c8d121797bc9aa1baf4e7e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 12 Dec 2007 11:24:19 -0800 Subject: [TIPC]: Fix semaphore handling. As noted by Kevin, tipc's release() does down_interruptible() and ignores the return value. So if signal_pending() we'll end up doing up() on a non-downed semaphore. Fix. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 6b792265dc0..24ddfd2ca38 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -253,7 +253,7 @@ static int release(struct socket *sock) dbg("sock_delete: %x\n",tsock); if (!tsock) return 0; - down_interruptible(&tsock->sem); + down(&tsock->sem); if (!sock->sk) { up(&tsock->sem); return 0; -- cgit v1.2.3 From 6f229d76b4c4a7fae601ea9398b23c2b426ab3b9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 12 Dec 2007 18:50:18 -0800 Subject: [SYNCPPP]: Endianness and 64bit fixes. * trivial annotations * long != 32bit, use __be32 * wrong endianness in sending CISCO_ADDR_REPLY Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/wan/syncppp.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index 232ecba5340..61e24b7a45a 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -107,24 +107,24 @@ struct ppp_header { u8 address; u8 control; - u16 protocol; + __be16 protocol; }; #define PPP_HEADER_LEN sizeof (struct ppp_header) struct lcp_header { u8 type; u8 ident; - u16 len; + __be16 len; }; #define LCP_HEADER_LEN sizeof (struct lcp_header) struct cisco_packet { - u32 type; - u32 par1; - u32 par2; - u16 rel; - u16 time0; - u16 time1; + __be32 type; + __be32 par1; + __be32 par2; + __be16 rel; + __be16 time0; + __be16 time1; }; #define CISCO_PACKET_LEN 18 #define CISCO_BIG_PACKET_LEN 20 @@ -139,7 +139,7 @@ static struct sk_buff_head tx_queue; static void sppp_keepalive (unsigned long dummy); static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, u8 ident, u16 len, void *data); -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); +static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2); static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); @@ -447,7 +447,7 @@ static void sppp_keepalive (unsigned long dummy) sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, sp->pp_rseq); else if (sp->lcp.state == LCP_STATE_OPENED) { - long nmagic = htonl (sp->lcp.magic); + __be32 nmagic = htonl (sp->lcp.magic); sp->lcp.echoid = ++sp->pp_seq; sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, sp->lcp.echoid, 4, &nmagic); @@ -667,7 +667,7 @@ badreq: dev->name, len); break; } - if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { + if (ntohl (*(__be32*)(h+1)) == sp->lcp.magic) { /* Line loopback mode detected. */ printk (KERN_WARNING "%s: loopback\n", dev->name); if_down (dev); @@ -680,7 +680,7 @@ badreq: sppp_lcp_open (sp); break; } - *(long*)(h+1) = htonl (sp->lcp.magic); + *(__be32 *)(h+1) = htonl (sp->lcp.magic); sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); break; case LCP_ECHO_REPLY: @@ -692,7 +692,7 @@ badreq: dev->name, len); break; } - if (ntohl (*(long*)(h+1)) != sp->lcp.magic) + if (ntohl(*(__be32 *)(h+1)) != sp->lcp.magic) sp->pp_alivecnt = 0; break; } @@ -765,7 +765,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) { struct in_device *in_dev; struct in_ifaddr *ifa; - __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ + __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */ #ifdef CONFIG_INET rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) @@ -782,8 +782,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) } rcu_read_unlock(); #endif - /* I hope both addr and mask are in the net order */ - sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); + sppp_cisco_send (sp, CISCO_ADDR_REPLY, ntohl(addr), ntohl(mask)); break; } } @@ -844,7 +843,7 @@ static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, * Send Cisco keepalive packet. */ -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) +static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2) { struct ppp_header *h; struct cisco_packet *ch; @@ -868,7 +867,7 @@ static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) ch->type = htonl (type); ch->par1 = htonl (par1); ch->par2 = htonl (par2); - ch->rel = -1; + ch->rel = htons(0xffff); ch->time0 = htons ((u16) (t >> 16)); ch->time1 = htons ((u16) t); -- cgit v1.2.3 From 4a9ecd5960e6a7814f6e3405807d49010ffe3a88 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 13 Dec 2007 09:32:04 -0800 Subject: [NETFILTER]: bridge: fix missing link layer headers on outgoing routed packets As reported by Damien Thebault, the double POSTROUTING hook invocation fix caused outgoing packets routed between two bridges to appear without a link-layer header. The reason for this is that we're skipping the br_nf_post_routing hook for routed packets now and don't save the original link layer header, but nevertheless tries to restore it on output, causing corruption. The root cause for this is that skb->nf_bridge has no clearly defined lifetime and is used to indicate all kind of things, but that is quite complicated to fix. For now simply don't touch these packets and handle them like packets from any other device. Tested-by: Damien Thebault Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter_bridge.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 533ee351a27..499aa937590 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -50,7 +50,8 @@ enum nf_br_hook_priorities { extern int nf_bridge_copy_header(struct sk_buff *skb); static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) { - if (skb->nf_bridge) + if (skb->nf_bridge && + skb->nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT)) return nf_bridge_copy_header(skb); return 0; } -- cgit v1.2.3 From f58adb757be48068e2bded3dd77ba072c22a10ff Mon Sep 17 00:00:00 2001 From: "Tom \"spot\" Callaway" Date: Thu, 13 Dec 2007 09:33:50 -0800 Subject: [ATM]: Fix compiler warning noise with FORE200E driver gcc throws these warnings with: CONFIG_ATM_FORE200E=m # CONFIG_ATM_FORE200E_PCA is not set drivers/atm/fore200e.c:2695: warning: 'fore200e_pca_detect' defined but not used drivers/atm/fore200e.c:2748: warning: 'fore200e_pca_remove_one' defined but not used By moving the #ifdef CONFIG_ATM_FORE200E_PCA around those two functions, the compiler warnings are silenced. Signed-off-by: Tom "spot" Callaway Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 8b12925fe7a..f97e050338f 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2689,7 +2689,7 @@ fore200e_init(struct fore200e* fore200e) return 0; } - +#ifdef CONFIG_ATM_FORE200E_PCA static int __devinit fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { @@ -2756,7 +2756,6 @@ static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev) } -#ifdef CONFIG_ATM_FORE200E_PCA static struct pci_device_id fore200e_pca_tbl[] = { { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &fore200e_bus[0] }, -- cgit v1.2.3 From f33e1d9fa20381afa3be7e7f560c59845bfa5cec Mon Sep 17 00:00:00 2001 From: Amos Waterland Date: Fri, 14 Dec 2007 11:30:22 -0800 Subject: [IPV4]: Updates to nfsroot documentation The difference between ip=off and ip=::::::off has been a cause of much confusion. Document how each behaves, and do not contradict ourselves by saying that "off" is the default when in fact "any" is the default and is descibed as being so lower in the file. Signed-off-by: Amos Waterland Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- Documentation/nfsroot.txt | 12 +++++++++--- net/ipv4/ipconfig.c | 20 +------------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/Documentation/nfsroot.txt b/Documentation/nfsroot.txt index 16a7cae2721..9b956a96936 100644 --- a/Documentation/nfsroot.txt +++ b/Documentation/nfsroot.txt @@ -92,8 +92,14 @@ ip=:::::: autoconfiguration. The parameter can appear alone as the value to the `ip' - parameter (without all the ':' characters before) in which case auto- - configuration is used. + parameter (without all the ':' characters before). If the value is + "ip=off" or "ip=none", no autoconfiguration will take place, otherwise + autoconfiguration will take place. The most common way to use this + is "ip=dhcp". + + Note that "ip=off" is not the same thing as "ip=::::::off", because in + the latter autoconfiguration will take place if any of DHCP, BOOTP or RARP + are compiled in the kernel. IP address of the client. @@ -142,7 +148,7 @@ ip=:::::: into the kernel will be used, regardless of the value of this option. - off or none: don't use autoconfiguration (default) + off or none: don't use autoconfiguration on or any: use any protocol available in the kernel dhcp: use DHCP bootp: use BOOTP diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index c5c107a0182..96400b0bd08 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1396,25 +1396,7 @@ late_initcall(ip_auto_config); /* * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel - * command line parameter. It consists of option fields separated by colons in - * the following order: - * - * :::::: - * - * Any of the fields can be empty which means to use a default value: - * - address given by BOOTP or RARP - * - address of host returning BOOTP or RARP packet - * - none, or the address returned by BOOTP - * - automatically determined from , or the - * one returned by BOOTP - * - in ASCII notation, or the name returned - * by BOOTP - * - use all available devices - * : - * off|none - don't do autoconfig at all (DEFAULT) - * on|any - use any configured protocol - * dhcp|bootp|rarp - use only the specified protocol - * both - use both BOOTP and RARP (not DHCP) + * command line parameter. See Documentation/nfsroot.txt. */ static int __init ic_proto_name(char *name) { -- cgit v1.2.3 From 3ae412544cde6d987e0e48778bd87bc96a5749df Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 16 Dec 2007 13:35:51 -0800 Subject: [BRIDGE]: Assign random address. Assigning a valid random address to bridge device solves problems when bridge device is brought up before adding real device to bridge. When the first real device is added to the bridge, it's address will overide the bridges random address. Note: any device added to a bridge must already have a valid ethernet address. br_add_if -> br_fdb_insert -> fdb_insert -> is_valid_ether_addr Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_device.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index c07bac5e3e1..bf7787395fe 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -157,8 +157,7 @@ static struct ethtool_ops br_ethtool_ops = { void br_dev_setup(struct net_device *dev) { - memset(dev->dev_addr, 0, ETH_ALEN); - + random_ether_addr(dev->dev_addr); ether_setup(dev); dev->do_ioctl = br_dev_ioctl; -- cgit v1.2.3 From cf6fc4a92400decda932e5ab97b46916919142b1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 16 Dec 2007 13:39:57 -0800 Subject: [IPV6]: Fix the return value of ipv6_getsockopt If CONFIG_NETFILTER if not selected when compile the kernel source code, ipv6_getsockopt will returen an EINVAL error if optname is not supported by the kernel. But if CONFIG_NETFILTER is selected, ENOPROTOOPT error will be return. This patch fix to always return ENOPROTOOPT error if optname argument of ipv6_getsockopt is not supported by the kernel. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/ipv6/ipv6_sockglue.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 1334fc174bc..8c5f80fd03a 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -1046,7 +1046,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, break; default: - return -EINVAL; + return -ENOPROTOOPT; } len = min_t(unsigned int, sizeof(int), len); if(put_user(len, optlen)) @@ -1069,9 +1069,8 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); #ifdef CONFIG_NETFILTER - /* we need to exclude all possible EINVALs except default case */ - if (err == -EINVAL && optname != IPV6_ADDRFORM && - optname != MCAST_MSFILTER) { + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { int len; if (get_user(len, optlen)) @@ -1108,9 +1107,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); #ifdef CONFIG_NETFILTER - /* we need to exclude all possible EINVALs except default case */ - if (err == -EINVAL && optname != IPV6_ADDRFORM && - optname != MCAST_MSFILTER) { + /* we need to exclude all possible ENOPROTOOPTs except default case */ + if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { int len; if (get_user(len, optlen)) -- cgit v1.2.3 From 488faa2ae32c2f8b1ffda5c7fae5eb7c979acc15 Mon Sep 17 00:00:00 2001 From: Satoru SATOH Date: Sun, 16 Dec 2007 14:00:19 -0800 Subject: [IPV4]: Make tcp_input_metrics() get minimum RTO via tcp_rto_min() tcp_input_metrics() refers to the built-time constant TCP_RTO_MIN regardless of configured minimum RTO with iproute2. Signed-off-by: Satoru SATOH Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b9e429d2d1d..889c89362bf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -923,7 +923,7 @@ static void tcp_init_metrics(struct sock *sk) } if (dst_metric(dst, RTAX_RTTVAR) > tp->mdev) { tp->mdev = dst_metric(dst, RTAX_RTTVAR); - tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); + tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); } tcp_set_rto(sk); tcp_bound_rto(sk); -- cgit v1.2.3 From 215f7b08f2a142ec19f4bd3d6de263e68b877955 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 16 Dec 2007 14:02:07 -0800 Subject: [AX25]: Locking dependencies fix in ax25_disconnect(). Bernard Pidoux reported these lockdep warnings: [ INFO: possible irq lock inversion dependency detected ] 2.6.23.1 #1 --------------------------------------------------------- fpac/4933 just changed the state of lock: (slock-AF_AX25){--..}, at: [] ax25_disconnect+0x46/0xaf [ax25] but this lock was taken by another, soft-irq-safe lock in the past: (ax25_list_lock){-+..} and interrupts could create inverse lock ordering between them. [...] [ INFO: inconsistent lock state ] 2.6.23.1 #1 --------------------------------- inconsistent {in-softirq-W} -> {softirq-on-W} usage. ax25_call/4005 [HC0[0]:SC0[0]:HE1:SE1] takes: (slock-AF_AX25){-+..}, at: [] ax25_disconnect+0x46/0xaf [ax25] [...] This means slock-AF_AX25 could be taken both from softirq and process context with softirqs enabled, so it's endangered itself, but also makes ax25_list_lock vulnerable. It was not 100% verified if the real lockup can happen, but this fix isn't very costly and looks safe anyway. (It was tested by Bernard with 2.6.23.9 and 2.6.24-rc5 kernels.) Reported_by: Bernard Pidoux Tested_by: Bernard Pidoux Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/ax25/ax25_subr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 5fe9b2a6697..d8f21573317 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -279,6 +279,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason) ax25_link_failed(ax25, reason); if (ax25->sk != NULL) { + local_bh_disable(); bh_lock_sock(ax25->sk); ax25->sk->sk_state = TCP_CLOSE; ax25->sk->sk_err = reason; @@ -288,5 +289,6 @@ void ax25_disconnect(ax25_cb *ax25, int reason) sock_set_flag(ax25->sk, SOCK_DEAD); } bh_unlock_sock(ax25->sk); + local_bh_enable(); } } -- cgit v1.2.3 From ef5d4cf2f9aae4e09883d2d664e367a16b47d857 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Sun, 16 Dec 2007 14:05:45 -0800 Subject: [SCTP]: Flush fragment queue when exiting partial delivery. At the end of partial delivery, we may have complete messages sitting on the fragment queue. These messages are stuck there until a new fragment arrives. This can comletely stall a given association. When clearing partial delivery state, flush any complete messages from the fragment queue and send them on their way up. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/ulpqueue.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 4908041ffb3..1733fa29a50 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -53,6 +53,7 @@ static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq, struct sctp_ulpevent *); static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *, struct sctp_ulpevent *); +static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq); /* 1st Level Abstractions */ @@ -190,6 +191,7 @@ static void sctp_ulpq_set_pd(struct sctp_ulpq *ulpq) static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq) { ulpq->pd_mode = 0; + sctp_ulpq_reasm_drain(ulpq); return sctp_clear_pd(ulpq->asoc->base.sk, ulpq->asoc); } @@ -699,6 +701,37 @@ void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *ulpq, __u32 fwd_tsn) } } +/* + * Drain the reassembly queue. If we just cleared parted delivery, it + * is possible that the reassembly queue will contain already reassembled + * messages. Retrieve any such messages and give them to the user. + */ +static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq) +{ + struct sctp_ulpevent *event = NULL; + struct sk_buff_head temp; + + if (skb_queue_empty(&ulpq->reasm)) + return; + + while ((event = sctp_ulpq_retrieve_reassembled(ulpq)) != NULL) { + /* Do ordering if needed. */ + if ((event) && (event->msg_flags & MSG_EOR)){ + skb_queue_head_init(&temp); + __skb_queue_tail(&temp, sctp_event2skb(event)); + + event = sctp_ulpq_order(ulpq, event); + } + + /* Send event to the ULP. 'event' is the + * sctp_ulpevent for very first SKB on the temp' list. + */ + if (event) + sctp_ulpq_tail_event(ulpq, event); + } +} + + /* Helper function to gather skbs that have possibly become * ordered by an an incoming chunk. */ -- cgit v1.2.3 From 497ba7f4c8113ed699a4fd793d1437f0c8f2da5e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 16 Dec 2007 14:07:36 -0800 Subject: [IRDA]: Race between open and disconnect in irda-usb. It seems to me that irda_usb_net_open() must set self->netopen under spinlock or disconnect() may fail to kill all URBs, if it is called while an interface is opened. Signed-off-by: Oliver Neukum Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/irda-usb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index c6355c00fd7..9081234ab45 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1168,6 +1168,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) static int irda_usb_net_open(struct net_device *netdev) { struct irda_usb_cb *self; + unsigned long flags; char hwname[16]; int i; @@ -1177,13 +1178,16 @@ static int irda_usb_net_open(struct net_device *netdev) self = (struct irda_usb_cb *) netdev->priv; IRDA_ASSERT(self != NULL, return -1;); + spin_lock_irqsave(&self->lock, flags); /* Can only open the device if it's there */ if(!self->present) { + spin_unlock_irqrestore(&self->lock, flags); IRDA_WARNING("%s(), device not present!\n", __FUNCTION__); return -1; } if(self->needspatch) { + spin_unlock_irqrestore(&self->lock, flags); IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ; return -EIO ; } @@ -1198,6 +1202,7 @@ static int irda_usb_net_open(struct net_device *netdev) /* To do *before* submitting Rx urbs and starting net Tx queue * Jean II */ self->netopen = 1; + spin_unlock_irqrestore(&self->lock, flags); /* * Now that everything should be initialized properly, -- cgit v1.2.3 From 0ff804348d66550e7dd1d6781c65403b312e2da2 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Sun, 16 Dec 2007 14:08:22 -0800 Subject: [IRDA]: mcs7780 needs to free allocated rx buffer. While testing the mcs7780 based IrDA USB dongle I've stumbled upon memory leak in mcs_net_close(). Patch below fixes it. Signed-off-by: Hinko Kocevar Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/mcs7780.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index 0b769192d4c..93916cf33f2 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -677,6 +677,8 @@ static int mcs_net_close(struct net_device *netdev) /* Stop transmit processing */ netif_stop_queue(netdev); + kfree_skb(mcs->rx_buff.skb); + /* kill and free the receive and transmit URBs */ usb_kill_urb(mcs->rx_urb); usb_free_urb(mcs->rx_urb); -- cgit v1.2.3 From 2638698df30b7b57a8dad7029a0c89fe6c4f6783 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Sun, 16 Dec 2007 14:08:58 -0800 Subject: [IRDA]: irlmp_unregister_link() needs to free lsaps. While testing the mcs7780 based IrDA USB dongle I've stumbled upon memory leak in irlmp_unregister_link(). Hashbin for lsaps is created in irlmp_register_link and should probably be freed in irlmp_unregister_link(). Signed-off-by: Hinko Kocevar Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- net/irda/irlmp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index cedff8068fb..f24cb755908 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -353,6 +353,7 @@ void irlmp_unregister_link(__u32 saddr) /* Final cleanup */ del_timer(&link->idle_timer); link->magic = 0; + hashbin_delete(link->lsaps, (FREE_FUNC) __irlmp_close_lsap); kfree(link); } } -- cgit v1.2.3 From ea332912b8a2e0b2f51ac3b6c197b71d3a18cbb7 Mon Sep 17 00:00:00 2001 From: Olaf Hartmann Date: Sun, 16 Dec 2007 14:09:44 -0800 Subject: [IRDA]: stir4200 fixes. From: Olaf Hartmann The attached patch observes the stir4200 fifo size and will clear the fifo, if the size is increasing, while it should be transmitting bytes Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/stir4200.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 042bc2f0417..e59c485bc49 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -142,9 +142,6 @@ enum StirCtrl2Mask { }; enum StirFifoCtlMask { - FIFOCTL_EOF = 0x80, - FIFOCTL_UNDER = 0x40, - FIFOCTL_OVER = 0x20, FIFOCTL_DIR = 0x10, FIFOCTL_CLR = 0x08, FIFOCTL_EMPTY = 0x04, @@ -594,9 +591,10 @@ static int fifo_txwait(struct stir_cb *stir, int space) { int err; unsigned long count, status; + unsigned long prev_count = 0x1fff; /* Read FIFO status and count */ - for(;;) { + for (;; prev_count = count) { err = read_reg(stir, REG_FIFOCTL, stir->fifo_status, FIFO_REGS_SIZE); if (unlikely(err != FIFO_REGS_SIZE)) { @@ -629,6 +627,10 @@ static int fifo_txwait(struct stir_cb *stir, int space) if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count) return 0; + /* queue confused */ + if (prev_count < count) + break; + /* estimate transfer time for remaining chars */ msleep((count * 8000) / stir->speed); } -- cgit v1.2.3 From a26e01d71622a4cecad06ce85bcab3ed878e7f83 Mon Sep 17 00:00:00 2001 From: Richard Knutsson Date: Sun, 16 Dec 2007 14:10:33 -0800 Subject: [IRDA]: irda parameters warning fixes. This patch fixes: CHECK /home/kernel/src/net/irda/parameters.c /home/kernel/src/net/irda/parameters.c:466:2: warning: Using plain integer as NULL pointer /home/kernel/src/net/irda/parameters.c:520:2: warning: Using plain integer as NULL pointer /home/kernel/src/net/irda/parameters.c:573:2: warning: Using plain integer as NULL pointer Signed-off-by: Richard Knutsson Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- net/irda/parameters.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/irda/parameters.c b/net/irda/parameters.c index 2627dad7cd8..7183e9ef799 100644 --- a/net/irda/parameters.c +++ b/net/irda/parameters.c @@ -463,7 +463,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len, int n = 0; IRDA_ASSERT(buf != NULL, return ret;); - IRDA_ASSERT(info != 0, return ret;); + IRDA_ASSERT(info != NULL, return ret;); pi_minor = pi & info->pi_mask; pi_major = pi >> info->pi_major_offset; @@ -517,7 +517,7 @@ static int irda_param_extract(void *self, __u8 *buf, int len, int n = 0; IRDA_ASSERT(buf != NULL, return ret;); - IRDA_ASSERT(info != 0, return ret;); + IRDA_ASSERT(info != NULL, return ret;); pi_minor = buf[n] & info->pi_mask; pi_major = buf[n] >> info->pi_major_offset; @@ -570,7 +570,7 @@ int irda_param_extract_all(void *self, __u8 *buf, int len, int n = 0; IRDA_ASSERT(buf != NULL, return ret;); - IRDA_ASSERT(info != 0, return ret;); + IRDA_ASSERT(info != NULL, return ret;); /* * Parse all parameters. Each parameter must be at least two bytes -- cgit v1.2.3