From 8fa45a70badf6ce2c57421c17e86e8967ce0d478 Mon Sep 17 00:00:00 2001 From: Ang Way Chuang Date: Thu, 13 Dec 2012 23:08:39 +0000 Subject: bridge: remove temporary variable for MLDv2 maximum response code computation As suggested by Stephen Hemminger, this remove the temporary variable introduced in commit eca2a43bb0d2c6ebd528be6acb30a88435abe307 ("bridge: fix icmpv6 endian bug and other sparse warnings") Signed-off-by: Ang Way Chuang Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1093c89..2561af9 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1165,7 +1165,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, if (max_delay) group = &mld->mld_mca; } else if (skb->len >= sizeof(*mld2q)) { - u16 mrc; if (!pskb_may_pull(skb, sizeof(*mld2q))) { err = -EINVAL; goto out; @@ -1173,8 +1172,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, mld2q = (struct mld2_query *)icmp6_hdr(skb); if (!mld2q->mld2q_nsrcs) group = &mld2q->mld2q_mca; - mrc = ntohs(mld2q->mld2q_mrc); - max_delay = mrc ? MLDV2_MRC(mrc) : 1; + max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1; } if (!group) -- cgit v1.1 From 1e9f954516ee03251e0ac2e98cad2e4be6ce9958 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 14 Dec 2012 01:03:03 +0000 Subject: mac802154: fix destructon ordering for ieee802154 devices mutex_destroy() must be called before wpan_phy_free(), because it puts the last reference and frees memory. Catched as overwritten poison in kmalloc-2048. Signed-off-by: Konstantin Khlebnikov Cc: Alexander Smirnov Cc: Dmitry Eremin-Solenikov Cc: David S. Miller Cc: linux-zigbee-devel@lists.sourceforge.net Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/mac802154/ieee802154_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index e748aed..b7c7f81 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c @@ -224,9 +224,9 @@ void ieee802154_free_device(struct ieee802154_dev *hw) BUG_ON(!list_empty(&priv->slaves)); - wpan_phy_free(priv->phy); - mutex_destroy(&priv->slaves_mtx); + + wpan_phy_free(priv->phy); } EXPORT_SYMBOL(ieee802154_free_device); -- cgit v1.1 From 093d04d42fa094f6740bb188f0ad0c215ff61e2c Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Fri, 14 Dec 2012 02:59:59 +0000 Subject: ipv6: Change skb->data before using icmpv6_notify() to propagate redirect In function ndisc_redirect_rcv(), the skb->data points to the transport header, but function icmpv6_notify() need the skb->data points to the inner IP packet. So before using icmpv6_notify() to propagate redirect, change skb->data to point the inner IP packet that triggered the sending of the Redirect, and introduce struct rd_msg to make it easy. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'net') diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f2a007b..6574175 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1314,6 +1314,12 @@ out: static void ndisc_redirect_rcv(struct sk_buff *skb) { + u8 *hdr; + struct ndisc_options ndopts; + struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb); + u32 ndoptlen = skb->tail - (skb->transport_header + + offsetof(struct rd_msg, opt)); + #ifdef CONFIG_IPV6_NDISC_NODETYPE switch (skb->ndisc_nodetype) { case NDISC_NODETYPE_HOST: @@ -1330,6 +1336,17 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) return; } + if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) + return; + + if (!ndopts.nd_opts_rh) + return; + + hdr = (u8 *)ndopts.nd_opts_rh; + hdr += 8; + if (!pskb_pull(skb, hdr - skb_transport_header(skb))) + return; + icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); } -- cgit v1.1 From e337e24d6624e74a558aa69071e112a65f7b5758 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Fri, 14 Dec 2012 04:07:58 +0000 Subject: inet: Fix kmemleak in tcp_v4/6_syn_recv_sock and dccp_v4/6_request_recv_sock If in either of the above functions inet_csk_route_child_sock() or __inet_inherit_port() fails, the newsk will not be freed: unreferenced object 0xffff88022e8a92c0 (size 1592): comm "softirq", pid 0, jiffies 4294946244 (age 726.160s) hex dump (first 32 bytes): 0a 01 01 01 0a 01 01 02 00 00 00 00 a7 cc 16 00 ................ 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x21/0x3e [] kmem_cache_alloc+0xb5/0xc5 [] sk_prot_alloc.isra.53+0x2b/0xcd [] sk_clone_lock+0x16/0x21e [] inet_csk_clone_lock+0x10/0x7b [] tcp_create_openreq_child+0x21/0x481 [] tcp_v4_syn_recv_sock+0x3a/0x23b [] tcp_check_req+0x29f/0x416 [] tcp_v4_do_rcv+0x161/0x2bc [] tcp_v4_rcv+0x6c9/0x701 [] ip_local_deliver_finish+0x70/0xc4 [] ip_local_deliver+0x4e/0x7f [] ip_rcv_finish+0x1fc/0x233 [] ip_rcv+0x217/0x267 [] __netif_receive_skb+0x49e/0x553 [] netif_receive_skb+0x50/0x82 This happens, because sk_clone_lock initializes sk_refcnt to 2, and thus a single sock_put() is not enough to free the memory. Additionally, things like xfrm, memcg, cookie_values,... may have been initialized. We have to free them properly. This is fixed by forcing a call to tcp_done(), ending up in inet_csk_destroy_sock, doing the final sock_put(). tcp_done() is necessary, because it ends up doing all the cleanup on xfrm, memcg, cookie_values, xfrm,... Before calling tcp_done, we have to set the socket to SOCK_DEAD, to force it entering inet_csk_destroy_sock. To avoid the warning in inet_csk_destroy_sock, inet_num has to be set to 0. As inet_csk_destroy_sock does a dec on orphan_count, we first have to increase it. Calling tcp_done() allows us to remove the calls to tcp_clear_xmit_timer() and tcp_cleanup_congestion_control(). A similar approach is taken for dccp by calling dccp_done(). This is in the kernel since 093d282321 (tproxy: fix hash locking issue when using port redirection in __inet_inherit_port()), thus since version >= 2.6.37. Signed-off-by: Christoph Paasch Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 4 ++-- net/dccp/ipv6.c | 3 ++- net/ipv4/inet_connection_sock.c | 16 ++++++++++++++++ net/ipv4/tcp_ipv4.c | 6 ++---- net/ipv6/tcp_ipv6.c | 3 ++- 5 files changed, 24 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 176ecdb..4f9f5eb 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -439,8 +439,8 @@ exit: NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto exit; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 56840b2..6e05981 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -585,7 +585,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, newinet->inet_rcv_saddr = LOOPBACK4_IPV6; if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto out; } __inet6_hash(newsk, NULL); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 2026542..d0670f0 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -710,6 +710,22 @@ void inet_csk_destroy_sock(struct sock *sk) } EXPORT_SYMBOL(inet_csk_destroy_sock); +/* This function allows to force a closure of a socket after the call to + * tcp/dccp_create_openreq_child(). + */ +void inet_csk_prepare_forced_close(struct sock *sk) +{ + /* sk_clone_lock locked the socket and set refcnt to 2 */ + bh_unlock_sock(sk); + sock_put(sk); + + /* The below has to be done to allow calling inet_csk_destroy_sock */ + sock_set_flag(sk, SOCK_DEAD); + percpu_counter_inc(sk->sk_prot->orphan_count); + inet_sk(sk)->inet_num = 0; +} +EXPORT_SYMBOL(inet_csk_prepare_forced_close); + int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) { struct inet_sock *inet = inet_sk(sk); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1ed2307..54139fa 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1767,10 +1767,8 @@ exit: NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - tcp_clear_xmit_timers(newsk); - tcp_cleanup_congestion_control(newsk); - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto exit; } EXPORT_SYMBOL(tcp_v4_syn_recv_sock); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6565cf5..93825dd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1288,7 +1288,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, #endif if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto out; } __inet6_hash(newsk, NULL); -- cgit v1.1 From 0d0863b02002c25140a1b9e113b81211bcc780e8 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 14 Dec 2012 15:22:01 +0000 Subject: sctp: Change defaults on cookie hmac selection Recently I posted commit 3c68198e75 which made selection of the cookie hmac algorithm selectable. This is all well and good, but Linus noted that it changes the default config: http://marc.info/?l=linux-netdev&m=135536629004808&w=2 I've modified the sctp Kconfig file to reflect the recommended way of making this choice, using the thermal driver example specified, and brought the defaults back into line with the way they were prior to my origional patch Also, on Linus' suggestion, re-adding ability to select default 'none' hmac algorithm, so we don't needlessly bloat the kernel by forcing a non-none default. This also led me to note that we won't honor the default none condition properly because of how sctp_net_init is encoded. Fix that up as well. Tested by myself (allbeit fairly quickly). All configuration combinations seems to work soundly. Signed-off-by: Neil Horman CC: David Miller CC: Linus Torvalds CC: Vlad Yasevich CC: linux-sctp@vger.kernel.org Signed-off-by: David S. Miller --- net/sctp/Kconfig | 27 +++++++++++++++++++++++++-- net/sctp/protocol.c | 4 ++-- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index a9edd2e..c262106 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -66,12 +66,36 @@ config SCTP_DBG_OBJCNT 'cat /proc/net/sctp/sctp_dbg_objcnt' If unsure, say N +choice + prompt "Default SCTP cookie HMAC encoding" + default SCTP_COOKIE_HMAC_MD5 + help + This option sets the default sctp cookie hmac algorithm + when in doubt select 'md5' + +config SCTP_DEFAULT_COOKIE_HMAC_MD5 + bool "Enable optional MD5 hmac cookie generation" + help + Enable optional MD5 hmac based SCTP cookie generation + select SCTP_COOKIE_HMAC_MD5 + +config SCTP_DEFAULT_COOKIE_HMAC_SHA1 + bool "Enable optional SHA1 hmac cookie generation" + help + Enable optional SHA1 hmac based SCTP cookie generation + select SCTP_COOKIE_HMAC_SHA1 + +config SCTP_DEFAULT_COOKIE_HMAC_NONE + bool "Use no hmac alg in SCTP cookie generation" + help + Use no hmac algorithm in SCTP cookie generation + +endchoice config SCTP_COOKIE_HMAC_MD5 bool "Enable optional MD5 hmac cookie generation" help Enable optional MD5 hmac based SCTP cookie generation - default y select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 @@ -79,7 +103,6 @@ config SCTP_COOKIE_HMAC_SHA1 bool "Enable optional SHA1 hmac cookie generation" help Enable optional SHA1 hmac based SCTP cookie generation - default y select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 2c7785b..f898b1c 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1191,9 +1191,9 @@ static int __net_init sctp_net_init(struct net *net) net->sctp.cookie_preserve_enable = 1; /* Default sctp sockets to use md5 as their hmac alg */ -#if defined (CONFIG_CRYPTO_MD5) +#if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5) net->sctp.sctp_hmac_alg = "md5"; -#elif defined (CONFIG_CRYPTO_SHA1) +#elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1) net->sctp.sctp_hmac_alg = "sha1"; #else net->sctp.sctp_hmac_alg = NULL; -- cgit v1.1 From ccb1c31a7a8744cd153a7d92b726a56b56ad61d3 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 14 Dec 2012 22:09:51 +0000 Subject: bridge: add flags to distinguish permanent mdb entires This patch adds a flag to each mdb entry, so that we can distinguish permanent entries with temporary entries. Cc: Herbert Xu Cc: Stephen Hemminger Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_mdb.c | 9 ++++++--- net/bridge/br_multicast.c | 8 +++++--- net/bridge/br_private.h | 4 +++- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 6f0a2ee..9cf5d2b 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -83,6 +83,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, if (port) { struct br_mdb_entry e; e.ifindex = port->dev->ifindex; + e.state = p->state; e.addr.u.ip4 = p->addr.u.ip4; #if IS_ENABLED(CONFIG_IPV6) e.addr.u.ip6 = p->addr.u.ip6; @@ -253,6 +254,8 @@ static bool is_valid_mdb_entry(struct br_mdb_entry *entry) #endif } else return false; + if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) + return false; return true; } @@ -310,7 +313,7 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, } static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, - struct br_ip *group) + struct br_ip *group, unsigned char state) { struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; @@ -336,7 +339,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, break; } - p = br_multicast_new_port_group(port, group, *pp); + p = br_multicast_new_port_group(port, group, *pp, state); if (unlikely(!p)) return -ENOMEM; rcu_assign_pointer(*pp, p); @@ -373,7 +376,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, #endif spin_lock_bh(&br->multicast_lock); - ret = br_mdb_add_group(br, p, &ip); + ret = br_mdb_add_group(br, p, &ip, entry->state); spin_unlock_bh(&br->multicast_lock); return ret; } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2561af9..dce9def 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -279,7 +279,7 @@ static void br_multicast_port_group_expired(unsigned long data) spin_lock(&br->multicast_lock); if (!netif_running(br->dev) || timer_pending(&pg->timer) || - hlist_unhashed(&pg->mglist)) + hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT) goto out; br_multicast_del_pg(br, pg); @@ -622,7 +622,8 @@ out: struct net_bridge_port_group *br_multicast_new_port_group( struct net_bridge_port *port, struct br_ip *group, - struct net_bridge_port_group __rcu *next) + struct net_bridge_port_group __rcu *next, + unsigned char state) { struct net_bridge_port_group *p; @@ -632,6 +633,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( p->addr = *group; p->port = port; + p->state = state; rcu_assign_pointer(p->next, next); hlist_add_head(&p->mglist, &port->mglist); setup_timer(&p->timer, br_multicast_port_group_expired, @@ -674,7 +676,7 @@ static int br_multicast_add_group(struct net_bridge *br, break; } - p = br_multicast_new_port_group(port, group, *pp); + p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY); if (unlikely(!p)) goto err; rcu_assign_pointer(*pp, p); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f21a739..49b85af4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -83,6 +83,7 @@ struct net_bridge_port_group { struct rcu_head rcu; struct timer_list timer; struct br_ip addr; + unsigned char state; }; struct net_bridge_mdb_entry @@ -443,7 +444,8 @@ extern void br_multicast_free_pg(struct rcu_head *head); extern struct net_bridge_port_group *br_multicast_new_port_group( struct net_bridge_port *port, struct br_ip *group, - struct net_bridge_port_group *next); + struct net_bridge_port_group *next, + unsigned char state); extern void br_mdb_init(void); extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, struct br_ip *group, int type); -- cgit v1.1 From 4cb9d6eaf85ecdd266a9a5c6d825c56ca9eefc14 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sat, 15 Dec 2012 10:12:43 +0000 Subject: sctp: jsctp_sf_eat_sack: fix jprobes function signature mismatch Commit 24cb81a6a (sctp: Push struct net down into all of the state machine functions) introduced the net structure into all state machine functions, but jsctp_sf_eat_sack was not updated, hence when SCTP association probing is enabled in the kernel, any simple SCTP client/server program from userspace will panic the kernel. Cc: Vlad Yasevich Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/probe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/probe.c b/net/sctp/probe.c index bc6cd75..5f7518d 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c @@ -122,7 +122,8 @@ static const struct file_operations sctpprobe_fops = { .llseek = noop_llseek, }; -sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep, +sctp_disposition_t jsctp_sf_eat_sack(struct net *net, + const struct sctp_endpoint *ep, const struct sctp_association *asoc, const sctp_subtype_t type, void *arg, -- cgit v1.1 From df4841910758227cfc07ae645de781d687b3b215 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 16 Dec 2012 06:47:50 +0000 Subject: ipv6: Fix Makefile offload objects The following commit breaks IPv6 TCP transmission for me: Commit 75fe83c32248d99e6d5fe64155e519b78bb90481 Author: Vlad Yasevich Date: Fri Nov 16 09:41:21 2012 +0000 ipv6: Preserve ipv6 functionality needed by NET This patch fixes the typo "ipv6_offload" which should be "ipv6-offload". I don't know why not including the offload modules should break TCP. Disabling all offload options on the NIC didn't help. Outgoing pulseaudio traffic kept stalling. Signed-off-by: Simon Arlott Signed-off-by: David S. Miller --- net/ipv6/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 2068ac4..4ea2448 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -41,6 +41,6 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o obj-$(CONFIG_IPV6_GRE) += ip6_gre.o obj-y += addrconf_core.o exthdrs_core.o -obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6_offload) +obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o -- cgit v1.1 From 9f1e0ad0ad3e19fce3df864502e9f419204397d7 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 15 Dec 2012 15:09:19 +0000 Subject: netlink: change presentation of portid in procfs to unsigned Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index c8a1eb6..9ee52b6 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2059,7 +2059,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v) struct sock *s = v; struct netlink_sock *nlk = nlk_sk(s); - seq_printf(seq, "%pK %-3d %-6d %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", + seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", s, s->sk_protocol, nlk->portid, -- cgit v1.1 From 4e4b53768f1ddce38b7f6edcad3a063020ef0024 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 15 Dec 2012 15:42:19 +0000 Subject: netlink: validate addr_len on bind Otherwise an out of bounds read could happen. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9ee52b6..c0353d5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -669,6 +669,9 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; int err; + if (addr_len < sizeof(struct sockaddr_nl)) + return -EINVAL; + if (nladdr->nl_family != AF_NETLINK) return -EINVAL; -- cgit v1.1 From 3c4177716cd2e452229dd0b7c25d192c48c1e7ac Mon Sep 17 00:00:00 2001 From: chas williams - CONTRACTOR Date: Mon, 17 Dec 2012 06:00:01 +0000 Subject: atm: use scnprintf() instead of sprintf() As reported by Chen Gang , we should ensure there is enough space when formatting the sysfs buffers. Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- net/atm/atm_sysfs.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) (limited to 'net') diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index f49da58..350bf62 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -14,49 +14,45 @@ static ssize_t show_type(struct device *cdev, struct device_attribute *attr, char *buf) { struct atm_dev *adev = to_atm_dev(cdev); - return sprintf(buf, "%s\n", adev->type); + + return scnprintf(buf, PAGE_SIZE, "%s\n", adev->type); } static ssize_t show_address(struct device *cdev, struct device_attribute *attr, char *buf) { - char *pos = buf; struct atm_dev *adev = to_atm_dev(cdev); - int i; - - for (i = 0; i < (ESI_LEN - 1); i++) - pos += sprintf(pos, "%02x:", adev->esi[i]); - pos += sprintf(pos, "%02x\n", adev->esi[i]); - return pos - buf; + return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi); } static ssize_t show_atmaddress(struct device *cdev, struct device_attribute *attr, char *buf) { unsigned long flags; - char *pos = buf; struct atm_dev *adev = to_atm_dev(cdev); struct atm_dev_addr *aaddr; int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; - int i, j; + int i, j, count = 0; spin_lock_irqsave(&adev->lock, flags); list_for_each_entry(aaddr, &adev->local, entry) { for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { if (j == *fmt) { - pos += sprintf(pos, "."); + count += scnprintf(buf + count, + PAGE_SIZE - count, "."); ++fmt; j = 0; } - pos += sprintf(pos, "%02x", - aaddr->addr.sas_addr.prv[i]); + count += scnprintf(buf + count, + PAGE_SIZE - count, "%02x", + aaddr->addr.sas_addr.prv[i]); } - pos += sprintf(pos, "\n"); + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); } spin_unlock_irqrestore(&adev->lock, flags); - return pos - buf; + return count; } static ssize_t show_atmindex(struct device *cdev, @@ -64,25 +60,21 @@ static ssize_t show_atmindex(struct device *cdev, { struct atm_dev *adev = to_atm_dev(cdev); - return sprintf(buf, "%d\n", adev->number); + return scnprintf(buf, PAGE_SIZE, "%d\n", adev->number); } static ssize_t show_carrier(struct device *cdev, struct device_attribute *attr, char *buf) { - char *pos = buf; struct atm_dev *adev = to_atm_dev(cdev); - pos += sprintf(pos, "%d\n", - adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); - - return pos - buf; + return scnprintf(buf, PAGE_SIZE, "%d\n", + adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); } static ssize_t show_link_rate(struct device *cdev, struct device_attribute *attr, char *buf) { - char *pos = buf; struct atm_dev *adev = to_atm_dev(cdev); int link_rate; @@ -100,9 +92,7 @@ static ssize_t show_link_rate(struct device *cdev, default: link_rate = adev->link_rate * 8 * 53; } - pos += sprintf(pos, "%d\n", link_rate); - - return pos - buf; + return scnprintf(buf, PAGE_SIZE, "%d\n", link_rate); } static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); -- cgit v1.1 From 63233159fd4e596568f5f168ecb0879b61631d47 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 19 Dec 2012 09:13:48 +0000 Subject: bridge: Do not unregister all PF_BRIDGE rtnl operations Bridge fdb and link rtnl operations are registered in core/rtnetlink. Bridge mdb operations are registred in bridge/mdb. When removing bridge module, do not unregister ALL PF_BRIDGE ops since that would remove the ops from rtnetlink as well. Do remove mdb ops when bridge is destroyed. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/bridge/br_mdb.c | 7 +++++++ net/bridge/br_multicast.c | 1 + net/bridge/br_netlink.c | 1 - net/bridge/br_private.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 9cf5d2b..3e05cc3 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -482,3 +482,10 @@ void br_mdb_init(void) rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL); rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL); } + +void br_mdb_uninit(void) +{ + rtnl_unregister(PF_BRIDGE, RTM_GETMDB); + rtnl_unregister(PF_BRIDGE, RTM_NEWMDB); + rtnl_unregister(PF_BRIDGE, RTM_DELMDB); +} diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index dce9def..5391ca4 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1633,6 +1633,7 @@ void br_multicast_stop(struct net_bridge *br) del_timer_sync(&br->multicast_querier_timer); del_timer_sync(&br->multicast_query_timer); + br_mdb_uninit(); spin_lock_bh(&br->multicast_lock); mdb = mlock_dereference(br->mdb, br); if (!mdb) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index dead9df..97ba018 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -305,5 +305,4 @@ int __init br_netlink_init(void) void __exit br_netlink_fini(void) { rtnl_link_unregister(&br_link_ops); - rtnl_unregister_all(PF_BRIDGE); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 49b85af4..8d83be5 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -447,6 +447,7 @@ extern struct net_bridge_port_group *br_multicast_new_port_group( struct net_bridge_port_group *next, unsigned char state); extern void br_mdb_init(void); +extern void br_mdb_uninit(void); extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, struct br_ip *group, int type); -- cgit v1.1 From 09d7cf7d931c627b227decd080f4528d003ddbe6 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 18 Dec 2012 11:54:08 +0000 Subject: bridge: Correctly encode addresses when dumping mdb entries When dumping mdb table, set the addresses the kernel returns based on the address protocol type. Signed-off-by: Vlad Yasevich Acked-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_mdb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 3e05cc3..acc9f4c 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -84,9 +84,11 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, struct br_mdb_entry e; e.ifindex = port->dev->ifindex; e.state = p->state; - e.addr.u.ip4 = p->addr.u.ip4; + if (p->addr.proto == htons(ETH_P_IP)) + e.addr.u.ip4 = p->addr.u.ip4; #if IS_ENABLED(CONFIG_IPV6) - e.addr.u.ip6 = p->addr.u.ip6; + if (p->addr.proto == htons(ETH_P_IPV6)) + e.addr.u.ip6 = p->addr.u.ip6; #endif e.addr.proto = p->addr.proto; if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) { -- cgit v1.1 From bd7790286b4acd52ecbd8123b1ce052cf1b931b1 Mon Sep 17 00:00:00 2001 From: Cong Ding Date: Tue, 18 Dec 2012 12:08:56 +0000 Subject: ipv6: addrconf.c: remove unnecessary "if" the value of err is always negative if it goes to errout, so we don't need to check the value of err. Signed-off-by: Cong Ding Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6fca01f..408cac4a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -534,8 +534,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC); return; errout: - if (err < 0) - rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); + rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); } static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { -- cgit v1.1