From 3e6b3b2e34ac2c72fa05b5e4b20bd88d64c298dc Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 16 Mar 2007 15:00:46 -0700 Subject: [NET]: Copy mac_len in skb_clone() as well ANK says: "It is rarely used, that's wy it was not noticed. But in the places, where it is used, it should be disaster." Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/core/skbuff.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/core') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 820761f9eeef..702fa8f08747 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -463,6 +463,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) memcpy(n->cb, skb->cb, sizeof(skb->cb)); C(len); C(data_len); + C(mac_len); C(csum); C(local_df); n->cloned = 1; -- cgit v1.2.3 From ec25615b9ddd5c584b4066652840581fdb6c5e7a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 22 Mar 2007 12:24:38 -0700 Subject: [NET]: Fix fib_rules dump race fib_rules_dump needs to use list_for_each_entry_rcu to protect against concurrent changes to the rules list. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/core/fib_rules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/core') diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 215f1bff048f..3aea4e87d3d7 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -374,7 +374,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) return -EAFNOSUPPORT; rcu_read_lock(); - list_for_each_entry(rule, ops->rules_list, list) { + list_for_each_entry_rcu(rule, ops->rules_list, list) { if (idx < cb->args[0]) goto skip; -- cgit v1.2.3 From b6f99a211957910a07437f46ce54dcfb1755cf84 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 22 Mar 2007 12:27:49 -0700 Subject: [NET]: fix up misplaced inlines. Turning up the warnings on gcc makes it emit warnings about the placement of 'inline' in function declarations. Here's everything that was under net/ Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/core') diff --git a/net/core/sock.c b/net/core/sock.c index 8d65d6478dcd..27c4f62382bd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -808,7 +808,7 @@ lenout: * * (We also register the sk_lock with the lock validator.) */ -static void inline sock_lock_init(struct sock *sk) +static inline void sock_lock_init(struct sock *sk) { sock_lock_init_class_and_name(sk, af_family_slock_key_strings[sk->sk_family], -- cgit v1.2.3 From e1701c68c1d1aeb3213d7016593ea9a1d4309417 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 24 Mar 2007 12:46:02 -0700 Subject: [NET]: Fix fib_rules compatibility breakage Based upon a patch from Patrick McHardy. The fib_rules netlink attribute policy introduced in 2.6.19 broke userspace compatibilty. When specifying a rule with "from all" or "to all", iproute adds a zero byte long netlink attribute, but the policy requires all addresses to have a size equal to sizeof(struct in_addr)/sizeof(struct in6_addr), resulting in a validation error. Check attribute length of FRA_SRC/FRA_DST in the generic framework by letting the family specific rules implementation provide the length of an address. Report an error if address length is non zero but no address attribute is provided. Fix actual bug by checking address length for non-zero instead of relying on availability of attribute. Signed-off-by: Thomas Graf Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/core/fib_rules.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'net/core') diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 3aea4e87d3d7..d011819a8058 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -152,6 +152,28 @@ out: EXPORT_SYMBOL_GPL(fib_rules_lookup); +static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, + struct fib_rules_ops *ops) +{ + int err = -EINVAL; + + if (frh->src_len) + if (tb[FRA_SRC] == NULL || + frh->src_len > (ops->addr_size * 8) || + nla_len(tb[FRA_SRC]) != ops->addr_size) + goto errout; + + if (frh->dst_len) + if (tb[FRA_DST] == NULL || + frh->dst_len > (ops->addr_size * 8) || + nla_len(tb[FRA_DST]) != ops->addr_size) + goto errout; + + err = 0; +errout: + return err; +} + int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct fib_rule_hdr *frh = nlmsg_data(nlh); @@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (err < 0) goto errout; + err = validate_rulemsg(frh, tb, ops); + if (err < 0) + goto errout; + rule = kzalloc(ops->rule_size, GFP_KERNEL); if (rule == NULL) { err = -ENOMEM; @@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (err < 0) goto errout; + err = validate_rulemsg(frh, tb, ops); + if (err < 0) + goto errout; + list_for_each_entry(rule, ops->rules_list, list) { if (frh->action && (frh->action != rule->action)) continue; -- cgit v1.2.3 From ecbb416939da77c0d107409976499724baddce7b Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sat, 24 Mar 2007 12:52:16 -0700 Subject: [NET]: Fix neighbour destructor handling. ->neigh_destructor() is killed (not used), replaced with ->neigh_cleanup(), which is called when neighbor entry goes to dead state. At this point everything is still valid: neigh->dev, neigh->parms etc. The device should guarantee that dead neighbor entries (neigh->dead != 0) do not get private part initialized, otherwise nobody will cleanup it. I think this is enough for ipoib which is the only user of this thing. Initialization private part of neighbor entries happens in ipib start_xmit routine, which is not reached when device is down. But it would be better to add explicit test for neigh->dead in any case. Signed-off-by: David S. Miller --- net/core/neighbour.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'net/core') diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 3183142c6044..cfc60019cf92 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl) n->dead = 1; shrunk = 1; write_unlock(&n->lock); + if (n->parms->neigh_cleanup) + n->parms->neigh_cleanup(n); neigh_release(n); continue; } @@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) NEIGH_PRINTK2("neigh %p is stray.\n", n); } write_unlock(&n->lock); + if (n->parms->neigh_cleanup) + n->parms->neigh_cleanup(n); neigh_release(n); } } @@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh) kfree(hh); } - if (neigh->parms->neigh_destructor) - (neigh->parms->neigh_destructor)(neigh); - skb_queue_purge(&neigh->arp_queue); dev_put(neigh->dev); @@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg) *np = n->next; n->dead = 1; write_unlock(&n->lock); + if (n->parms->neigh_cleanup) + n->parms->neigh_cleanup(n); neigh_release(n); continue; } @@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl, } else np = &n->next; write_unlock(&n->lock); - if (release) + if (release) { + if (n->parms->neigh_cleanup) + n->parms->neigh_cleanup(n); neigh_release(n); + } } } } -- cgit v1.2.3 From 035832a2806408ff209a0cb94bd64ea7dcf4d222 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 24 Mar 2007 22:13:25 -0700 Subject: [NET_SCHED]: Fix ingress locking Ingress queueing uses a seperate lock for serializing enqueue operations, but fails to properly protect itself against concurrent changes to the qdisc tree. Use queue_lock for now since the real fix it quite intrusive. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/core') diff --git a/net/core/dev.c b/net/core/dev.c index cf71614dae93..5984b55311a1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1750,10 +1750,10 @@ static int ing_filter(struct sk_buff *skb) skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); - spin_lock(&dev->ingress_lock); + spin_lock(&dev->queue_lock); if ((q = dev->qdisc_ingress) != NULL) result = q->enqueue(skb, q); - spin_unlock(&dev->ingress_lock); + spin_unlock(&dev->queue_lock); } -- cgit v1.2.3 From c2805fbb8630abb95d94ce7adc3f97976f7e0367 Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Fri, 23 Mar 2007 00:31:16 +0000 Subject: [PATCH] WE-22 : prevent information leak on 64 bit Johannes Berg discovered that kernel space was leaking to userspace on 64 bit platform. He made a first patch to fix that. This is an improved version of his patch. Signed-off-by: Jean Tourrilhes Signed-off-by: John W. Linville --- net/core/rtnetlink.c | 3 +- net/core/wireless.c | 82 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 52 insertions(+), 33 deletions(-) (limited to 'net/core') diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 6055074c4b81..33ea8eac7fe0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -621,7 +621,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (err < 0) goto errout; - iw += IW_EV_POINT_OFF; + /* Payload is at an offset in buffer */ + iw = iw_buf + IW_EV_POINT_OFF; } #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ diff --git a/net/core/wireless.c b/net/core/wireless.c index 9936ab11e6e0..b07fe270a508 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -76,6 +76,9 @@ * o Change length in ESSID and NICK to strlen() instead of strlen()+1 * o Make standard_ioctl_num and standard_event_num unsigned * o Remove (struct net_device *)->get_wireless_stats() + * + * v10 - 16.3.07 - Jean II + * o Prevent leaking of kernel space in stream on 64 bits. */ /***************************** INCLUDES *****************************/ @@ -427,6 +430,21 @@ static const int event_type_size[] = { IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ }; +/* Size (in bytes) of various events, as packed */ +static const int event_type_pk_size[] = { + IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */ + 0, + IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */ + 0, + IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */ + IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */ + IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */ + 0, + IW_EV_POINT_PK_LEN, /* Without variable payload */ + IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */ + IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */ +}; + /************************ COMMON SUBROUTINES ************************/ /* * Stuff that may be used in various place or doesn't fit in one @@ -1217,7 +1235,7 @@ static int rtnetlink_standard_get(struct net_device * dev, memcpy(buffer + IW_EV_POINT_OFF, request, request_len); /* Use our own copy of wrqu */ wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF - + IW_EV_LCP_LEN); + + IW_EV_LCP_PK_LEN); /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, wrqu, NULL); @@ -1229,8 +1247,8 @@ static int rtnetlink_standard_get(struct net_device * dev, /* Get a temp copy of wrqu (skip pointer) */ memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, - ((char *) request) + IW_EV_LCP_LEN, - IW_EV_POINT_LEN - IW_EV_LCP_LEN); + ((char *) request) + IW_EV_LCP_PK_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_PK_LEN); /* Calculate space needed by arguments. Always allocate * for max space. Easier, and won't last long... */ @@ -1240,7 +1258,7 @@ static int rtnetlink_standard_get(struct net_device * dev, (wrqu_point.data.length > descr->max_tokens)) extra_size = (wrqu_point.data.length * descr->token_size); - buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; + buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; #ifdef WE_RTNETLINK_DEBUG printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", dev->name, extra_size, buffer_size); @@ -1254,15 +1272,15 @@ static int rtnetlink_standard_get(struct net_device * dev, /* Put wrqu in the right place (just before extra). * Leave space for IWE header and dummy pointer... - * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. */ - memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, ((char *) &wrqu_point) + IW_EV_POINT_OFF, - IW_EV_POINT_LEN - IW_EV_LCP_LEN); - wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); /* Extra comes logically after that. Offset +12 bytes. */ - extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; /* Call the handler */ ret = handler(dev, &info, wrqu, extra); @@ -1270,11 +1288,11 @@ static int rtnetlink_standard_get(struct net_device * dev, /* Calculate real returned length */ extra_size = (wrqu->data.length * descr->token_size); /* Re-adjust reply size */ - request->len = extra_size + IW_EV_POINT_LEN; + request->len = extra_size + IW_EV_POINT_PK_LEN; /* Put the iwe header where it should, i.e. scrap the * dummy pointer. */ - memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); #ifdef WE_RTNETLINK_DEBUG printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); @@ -1331,10 +1349,10 @@ static inline int rtnetlink_standard_set(struct net_device * dev, #endif /* WE_RTNETLINK_DEBUG */ /* Extract fixed header from request. This is properly aligned. */ - wrqu = &request->u; + wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); /* Check if wrqu is complete */ - hdr_len = event_type_size[descr->header_type]; + hdr_len = event_type_pk_size[descr->header_type]; if(request_len < hdr_len) { #ifdef WE_RTNETLINK_DEBUG printk(KERN_DEBUG @@ -1359,7 +1377,7 @@ static inline int rtnetlink_standard_set(struct net_device * dev, /* Put wrqu in the right place (skip pointer) */ memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, - wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); /* Don't forget about the event code... */ wrqu = &wrqu_point; @@ -1483,7 +1501,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, hdr_len = extra_size; extra_size = 0; } else { - hdr_len = IW_EV_POINT_LEN; + hdr_len = IW_EV_POINT_PK_LEN; } /* Check if wrqu is complete */ @@ -1514,7 +1532,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, memcpy(buffer + IW_EV_POINT_OFF, request, request_len); /* Use our own copy of wrqu */ wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF - + IW_EV_LCP_LEN); + + IW_EV_LCP_PK_LEN); /* No extra arguments. Trivial to handle */ ret = handler(dev, &info, wrqu, (char *) wrqu); @@ -1523,7 +1541,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, char * extra; /* Buffer for full reply */ - buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; + buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; #ifdef WE_RTNETLINK_DEBUG printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", @@ -1538,15 +1556,15 @@ static inline int rtnetlink_private_get(struct net_device * dev, /* Put wrqu in the right place (just before extra). * Leave space for IWE header and dummy pointer... - * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. */ - memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, - ((char *) request) + IW_EV_LCP_LEN, - IW_EV_POINT_LEN - IW_EV_LCP_LEN); - wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_PK_LEN, + IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); /* Extra comes logically after that. Offset +12 bytes. */ - extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; /* Call the handler */ ret = handler(dev, &info, wrqu, extra); @@ -1556,11 +1574,11 @@ static inline int rtnetlink_private_get(struct net_device * dev, if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) extra_size = adjust_priv_size(descr->get_args, wrqu); /* Re-adjust reply size */ - request->len = extra_size + IW_EV_POINT_LEN; + request->len = extra_size + IW_EV_POINT_PK_LEN; /* Put the iwe header where it should, i.e. scrap the * dummy pointer. */ - memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); #ifdef WE_RTNETLINK_DEBUG printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); @@ -1641,14 +1659,14 @@ static inline int rtnetlink_private_set(struct net_device * dev, /* Does it fits in wrqu ? */ if((descr->set_args & IW_PRIV_SIZE_FIXED) && (extra_size <= IFNAMSIZ)) { - hdr_len = IW_EV_LCP_LEN + extra_size; + hdr_len = IW_EV_LCP_PK_LEN + extra_size; extra_size = 0; } else { - hdr_len = IW_EV_POINT_LEN; + hdr_len = IW_EV_POINT_PK_LEN; } /* Extract fixed header from request. This is properly aligned. */ - wrqu = &request->u; + wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); /* Check if wrqu is complete */ if(request_len < hdr_len) { @@ -1675,7 +1693,7 @@ static inline int rtnetlink_private_set(struct net_device * dev, /* Put wrqu in the right place (skip pointer) */ memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, - wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); /* Does it fits within bounds ? */ if(wrqu_point.data.length > (descr->set_args & @@ -1738,7 +1756,7 @@ int wireless_rtnetlink_get(struct net_device * dev, iw_handler handler; /* Check length */ - if(len < IW_EV_LCP_LEN) { + if(len < IW_EV_LCP_PK_LEN) { printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", dev->name, len); return -EINVAL; @@ -1822,7 +1840,7 @@ int wireless_rtnetlink_set(struct net_device * dev, iw_handler handler; /* Check length */ - if(len < IW_EV_LCP_LEN) { + if(len < IW_EV_LCP_PK_LEN) { printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", dev->name, len); return -EINVAL; -- cgit v1.2.3 From c01003c20563d1e75ec9828d21743919d2b43977 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 29 Mar 2007 11:46:52 -0700 Subject: [IFB]: Fix crash on input device removal The input_device pointer is not refcounted, which means the device may disappear while packets are queued, causing a crash when ifb passes packets with a stale skb->dev pointer to netif_rx(). Fix by storing the interface index instead and do a lookup where neccessary. Signed-off-by: Patrick McHardy Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++---- net/core/skbuff.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net/core') diff --git a/net/core/dev.c b/net/core/dev.c index 5984b55311a1..d44b8f1964fa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1741,8 +1741,8 @@ static int ing_filter(struct sk_buff *skb) if (dev->qdisc_ingress) { __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); if (MAX_RED_LOOP < ttl++) { - printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n", - skb->input_dev->name, skb->dev->name); + printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", + skb->iif, skb->dev->ifindex); return TC_ACT_SHOT; } @@ -1775,8 +1775,8 @@ int netif_receive_skb(struct sk_buff *skb) if (!skb->tstamp.off_sec) net_timestamp(skb); - if (!skb->input_dev) - skb->input_dev = skb->dev; + if (!skb->iif) + skb->iif = skb->dev->ifindex; orig_dev = skb_bond(skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 702fa8f08747..87573ae35b02 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -496,7 +496,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) n->tc_verd = SET_TC_VERD(skb->tc_verd,0); n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); n->tc_verd = CLR_TC_MUNGED(n->tc_verd); - C(input_dev); + C(iif); #endif skb_copy_secmark(n, skb); #endif -- cgit v1.2.3 From 83886b6b636173b206f475929e58fac75c6f2446 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 30 Mar 2007 13:34:27 -0700 Subject: [NET]: Change "not found" return value for rule lookup This changes the "not found" error return for the lookup function to -ESRCH so that it can be distinguished from the case where a rule or route resulting in -ENETUNREACH has been found during the search. It fixes a bug where if DECnet was compiled with routing support, but no routes were added to the routing table, it was failing to fall back to endnode routing. Signed-off-by: Steven Whitehouse Signed-off-by: Patrick Caulfield Signed-off-by: David S. Miller --- net/core/fib_rules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/core') diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index d011819a8058..7174ced75efc 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -143,7 +143,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, } } - err = -ENETUNREACH; + err = -ESRCH; out: rcu_read_unlock(); -- cgit v1.2.3 From 927498217c104aab27b81c785ce3a489491a8964 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 3 Apr 2007 00:07:30 -0600 Subject: [PATCH] net: Ignore sysfs network device rename bugs. The generic networking code ensures that no two networking devices have the same name, so there is no time except when sysfs has implementation bugs that device_rename when called from dev_change_name will fail. The current error handling for errors from device_rename in dev_change_name is wrong and results in an unusable and unrecoverable network device if device_rename is happens to return an error. This patch removes the buggy error handling. Which confines the mess when device_rename hits a problem to sysfs, instead of propagating it the rest of the network stack. Making linux a little more robust. Without this patch you can observe what happens when sysfs has a bug when CONFIG_SYSFS_DEPRECATED is not set and you attempt to rename a real network device to a name like (broken_parity_status, device, modalias, power, resource2, subsystem_vendor, class, driver, irq, msi_bus, resource, subsystem, uevent, config, enable, local_cpus, numa_node, resource0, subsystem_device, vendor) Greg has a patch that fixes the sysfs bugs but he doesn't trust it for a 2.6.21 timeframe. This patch which just ignores errors should be safe and it keeps the system from going completely wacky. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- net/core/dev.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'net/core') diff --git a/net/core/dev.c b/net/core/dev.c index d44b8f1964fa..4dc93cc4d5b7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -751,13 +751,10 @@ int dev_change_name(struct net_device *dev, char *newname) else strlcpy(dev->name, newname, IFNAMSIZ); - err = device_rename(&dev->dev, dev->name); - if (!err) { - hlist_del(&dev->name_hlist); - hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); - raw_notifier_call_chain(&netdev_chain, - NETDEV_CHANGENAME, dev); - } + device_rename(&dev->dev, dev->name); + hlist_del(&dev->name_hlist); + hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); + raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); return err; } -- cgit v1.2.3 From 09fe3ef46c5a2cc65d173df9518013e208eb3ba3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 12 Apr 2007 14:45:32 -0700 Subject: [PKTGEN]: Add try_to_freeze() The pktgen module prevents suspend-to-disk. Fix. Acked-by: "Michal Piotrowski" Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/core/pktgen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/core') diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 74a9a32b906d..4b01496dc33d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -129,6 +129,7 @@ #include #include #include +#include #include #include #include @@ -3333,6 +3334,8 @@ static int pktgen_thread_worker(void *arg) t->control &= ~(T_REMDEV); } + try_to_freeze(); + set_current_state(TASK_INTERRUPTIBLE); } -- cgit v1.2.3 From b4dfa0b1fb39c7ffe74741d60668825de6a47b69 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 17 Apr 2007 12:28:27 -0700 Subject: [NET]: Get rid of alloc_skb_from_cache Since this was added originally for Xen, and Xen has recently (~2.6.18) stopped using this function, we can safely get rid of it. Good timing too since this function has started to bit rot. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/skbuff.c | 55 ------------------------------------------------------- 1 file changed, 55 deletions(-) (limited to 'net/core') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 87573ae35b02..336958fbbcb2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -196,61 +196,6 @@ nodata: goto out; } -/** - * alloc_skb_from_cache - allocate a network buffer - * @cp: kmem_cache from which to allocate the data area - * (object size must be big enough for @size bytes + skb overheads) - * @size: size to allocate - * @gfp_mask: allocation mask - * - * Allocate a new &sk_buff. The returned buffer has no headroom and - * tail room of size bytes. The object has a reference count of one. - * The return is the buffer. On a failure the return is %NULL. - * - * Buffers may only be allocated from interrupts using a @gfp_mask of - * %GFP_ATOMIC. - */ -struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, - unsigned int size, - gfp_t gfp_mask) -{ - struct sk_buff *skb; - u8 *data; - - /* Get the HEAD */ - skb = kmem_cache_alloc(skbuff_head_cache, - gfp_mask & ~__GFP_DMA); - if (!skb) - goto out; - - /* Get the DATA. */ - size = SKB_DATA_ALIGN(size); - data = kmem_cache_alloc(cp, gfp_mask); - if (!data) - goto nodata; - - memset(skb, 0, offsetof(struct sk_buff, truesize)); - skb->truesize = size + sizeof(struct sk_buff); - atomic_set(&skb->users, 1); - skb->head = data; - skb->data = data; - skb->tail = data; - skb->end = data + size; - - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->gso_size = 0; - skb_shinfo(skb)->gso_segs = 0; - skb_shinfo(skb)->gso_type = 0; - skb_shinfo(skb)->frag_list = NULL; -out: - return skb; -nodata: - kmem_cache_free(skbuff_head_cache, skb); - skb = NULL; - goto out; -} - /** * __netdev_alloc_skb - allocate an skbuff for rx on a specific device * @dev: network device to receive on -- cgit v1.2.3 From 5e7d7fa57323dfb48fb09464cf4542daa7ce8a72 Mon Sep 17 00:00:00 2001 From: "Aubrey.Li" Date: Tue, 17 Apr 2007 12:40:20 -0700 Subject: [NET]: Fix UDP checksum issue in net poll mode. In net poll mode, the current checksum function doesn't consider the kind of packet which is padded to reach a specific minimum length. I believe that's the problem causing my test case failed. The following patch fixed this issue. Signed-off-by: Aubrey.Li Signed-off-by: David S. Miller --- net/core/netpoll.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net/core') diff --git a/net/core/netpoll.c b/net/core/netpoll.c index da1019451ccb..4581ece48bb2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb) if (skb->len < len || len < iph->ihl*4) goto out; + /* + * Our transport medium may have padded the buffer out. + * Now We trim to the true length of the frame. + */ + if (pskb_trim_rcsum(skb, len)) + goto out; + if (iph->protocol != IPPROTO_UDP) goto out; -- cgit v1.2.3 From c2ecba71717c4f60671175fd26083c35a4b9ad58 Mon Sep 17 00:00:00 2001 From: Pavel Emelianov Date: Tue, 17 Apr 2007 12:45:31 -0700 Subject: [NET]: Set a separate lockdep class for neighbour table's proxy_queue Otherwise the following calltrace will lead to a wrong lockdep warning: neigh_proxy_process() `- lock(neigh_table->proxy_queue.lock); arp_redo /* via tbl->proxy_redo */ arp_process neigh_event_ns neigh_update skb_queue_purge `- lock(neighbor->arp_queue.lock); This is not a deadlock actually, as neighbor table's proxy_queue and the neighbor's arp_queue are different queues. Lockdep thinks there is a deadlock as both queues are initialized with skb_queue_head_init() and thus have a common class. Signed-off-by: David S. Miller --- net/core/neighbour.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/core') diff --git a/net/core/neighbour.c b/net/core/neighbour.c index cfc60019cf92..841e3f32cab1 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1331,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms) kfree(parms); } +static struct lock_class_key neigh_table_proxy_queue_class; + void neigh_table_init_no_netlink(struct neigh_table *tbl) { unsigned long now = jiffies; @@ -1379,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) init_timer(&tbl->proxy_timer); tbl->proxy_timer.data = (unsigned long)tbl; tbl->proxy_timer.function = neigh_proxy_process; - skb_queue_head_init(&tbl->proxy_queue); + skb_queue_head_init_class(&tbl->proxy_queue, + &neigh_table_proxy_queue_class); tbl->last_flush = now; tbl->last_rand = now + tbl->parms.reachable_time * 20; -- cgit v1.2.3