From 06f3d7f973ec04290d86b7dd91b48d38d90433dc Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 18 Jun 2013 10:08:06 +0300 Subject: ipvs: SCTP ports should be writable in ICMP packets Make sure that SCTP ports are writable when embedded in ICMP from client, so that ip_vs_nat_icmp can translate them safely. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 05565d2b3a61..23b8eb53a569 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1442,7 +1442,8 @@ ignore_ipip: /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); - if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) + if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol || + IPPROTO_SCTP == cih->protocol) offset += 2 * sizeof(__u16); verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph); -- cgit v1.2.1 From c0353c7b5da4cbd2ab8227e84bbc9c79890f24ce Mon Sep 17 00:00:00 2001 From: Aydin Arik Date: Fri, 14 Jun 2013 18:56:31 +1200 Subject: ipv4: Fixed MD5 key lookups when adding/ removing MD5 to/ from TCP sockets. MD5 key lookups on a given TCP socket were being performed incorrectly. This fix alters parameter inputs to the MD5 lookup function tcp_md5_do_lookup, which is called by functions tcp_md5_do_add and tcp_md5_do_del. Specifically, the change now inputs the correct address and address family required to make a proper lookup. Signed-off-by: Aydin Arik Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 719652305a29..7999fc55c83b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1003,7 +1003,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, struct tcp_sock *tp = tcp_sk(sk); struct tcp_md5sig_info *md5sig; - key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); + key = tcp_md5_do_lookup(sk, addr, family); if (key) { /* Pre-existing entry - just update that one. */ memcpy(key->key, newkey, newkeylen); @@ -1048,7 +1048,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) struct tcp_md5sig_key *key; struct tcp_md5sig_info *md5sig; - key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); + key = tcp_md5_do_lookup(sk, addr, family); if (!key) return -ENOENT; hlist_del_rcu(&key->node); -- cgit v1.2.1 From a881ae1f625c599b460cc8f8a7fcb1c438f699ad Mon Sep 17 00:00:00 2001 From: Gao feng Date: Sun, 16 Jun 2013 11:14:30 +0800 Subject: ipv6: don't call addrconf_dst_alloc again when enable lo If we disable all of the net interfaces, and enable un-lo interface before lo interface, we already allocated the addrconf dst in ipv6_add_addr. So we shouldn't allocate it again when we enable lo interface. Otherwise the message below will be triggered. unregister_netdevice: waiting for sit1 to become free. Usage count = 1 This problem is introduced by commit 25fb6ca4ed9cad72f14f61629b68dc03c0d9713f "net IPv6 : Fix broken IPv6 routing table after loopback down-up" Signed-off-by: Gao feng Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1bbf744c2cc3..77b626136c23 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2655,6 +2655,9 @@ static void init_loopback(struct net_device *dev) if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) continue; + if (sp_ifa->rt) + continue; + sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); /* Failure cases are ignored */ -- cgit v1.2.1 From 142dcdd3c25fc7a3866bb06980e8f93a2ed7e050 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Wed, 19 Jun 2013 06:49:51 -0400 Subject: netfilter: nf_conntrack_ipv6: Plug sk_buff leak in fragment handling In commit 4cdd3408 ("netfilter: nf_conntrack_ipv6: improve fragmentation handling"), an sk_buff leak was introduced when dealing with reassembled packets by grabbing a reference to the original skb instead of the reassembled skb. At this point, the leak only impacted conntracks with an associated helper. In commit 58a317f1 ("netfilter: ipv6: add IPv6 NAT support"), the bug was expanded to include all reassembled packets with unconfirmed conntracks. Fix this by grabbing a reference to the proper reassembled skb. This closes netfilter bugzilla #823. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 97bcf2bae857..c9b6a6e6a1e8 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -204,7 +204,7 @@ static unsigned int __ipv6_conntrack_in(struct net *net, if (ct != NULL && !nf_ct_is_untracked(ct)) { help = nfct_help(ct); if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { - nf_conntrack_get_reasm(skb); + nf_conntrack_get_reasm(reasm); NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, (struct net_device *)in, (struct net_device *)out, -- cgit v1.2.1 From 5aed93875cd88502f04a0d4517b8a2d89a849773 Mon Sep 17 00:00:00 2001 From: Balazs Peter Odor Date: Sat, 22 Jun 2013 19:24:43 +0200 Subject: netfilter: nf_nat_sip: fix mangling In (b20ab9c netfilter: nf_ct_helper: better logging for dropped packets) there were some missing brackets around the logging information, thus always returning drop. Closes https://bugzilla.kernel.org/show_bug.cgi?id=60061 Signed-off-by: Balazs Peter Odor Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_nat_sip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c index 96ccdf78a29f..dac11f73868e 100644 --- a/net/netfilter/nf_nat_sip.c +++ b/net/netfilter/nf_nat_sip.c @@ -230,9 +230,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, &ct->tuplehash[!dir].tuple.src.u3, false); if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, - poff, plen, buffer, buflen)) + poff, plen, buffer, buflen)) { nf_ct_helper_log(skb, ct, "cannot mangle received"); return NF_DROP; + } } /* The rport= parameter (RFC 3581) contains the port number -- cgit v1.2.1 From 797a7d66d2048fe8a4ac1ba58c5d4752d64b1ac4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 21 Jun 2013 16:51:30 +0200 Subject: netfilter: ctnetlink: send event when conntrack label was modified commit 0ceabd83875b72a29f33db4ab703d6ba40ea4c58 (netfilter: ctnetlink: deliver labels to userspace) sets the event bit when we raced with another packet, instead of raising the event bit when the label bit is set for the first time. commit 9b21f6a90924dfe8e5e686c314ddb441fb06501e (netfilter: ctnetlink: allow userspace to modify labels) forgot to update the event mask in the "conntrack already exists" case. Both issues result in CTA_LABELS attribute not getting included in the conntrack event. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_labels.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c index 8fe2e99428b7..355d2ef08094 100644 --- a/net/netfilter/nf_conntrack_labels.c +++ b/net/netfilter/nf_conntrack_labels.c @@ -45,7 +45,7 @@ int nf_connlabel_set(struct nf_conn *ct, u16 bit) if (test_bit(bit, labels->bits)) return 0; - if (test_and_set_bit(bit, labels->bits)) + if (!test_and_set_bit(bit, labels->bits)) nf_conntrack_event_cache(IPCT_LABEL, ct); return 0; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 6d0f8a17c5b7..ecf065f94032 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1825,6 +1825,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, nf_conntrack_eventmask_report((1 << IPCT_REPLY) | (1 << IPCT_ASSURED) | (1 << IPCT_HELPER) | + (1 << IPCT_LABEL) | (1 << IPCT_PROTOINFO) | (1 << IPCT_NATSEQADJ) | (1 << IPCT_MARK), -- cgit v1.2.1 From c8fc51cfa758be945c6113a4b446e0159070f768 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Mon, 24 Jun 2013 17:04:02 +0800 Subject: netfilter: ipt_ULOG: fix incorrect setting of ulog timer The parameter of setup_timer should be &ulog->nlgroup[i]. the incorrect parameter will cause kernel panic in ulog_timer. Bug introducted in commit 355430671ad93546b34b4e91bdf720f3a704efa4 "netfilter: ipt_ULOG: add net namespace support for ipt_ULOG" ebt_ULOG doesn't have this problem. [ I have mangled this patch to fix nlgroup != 0 case, we were also crashing there --pablo ] Tested-by: George Spelvin Reported-by: Borislav Petkov Signed-off-by: Gao feng Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/ipt_ULOG.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index ff4b781b1056..32b0e978c8e0 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -125,15 +125,16 @@ static void ulog_send(struct ulog_net *ulog, unsigned int nlgroupnum) /* timer function to flush queue in flushtimeout time */ static void ulog_timer(unsigned long data) { + unsigned int groupnum = *((unsigned int *)data); struct ulog_net *ulog = container_of((void *)data, struct ulog_net, - nlgroup[*(unsigned int *)data]); + nlgroup[groupnum]); pr_debug("timer function called, calling ulog_send\n"); /* lock to protect against somebody modifying our structure * from ipt_ulog_target at the same time */ spin_lock_bh(&ulog->lock); - ulog_send(ulog, data); + ulog_send(ulog, groupnum); spin_unlock_bh(&ulog->lock); } @@ -407,8 +408,11 @@ static int __net_init ulog_tg_net_init(struct net *net) spin_lock_init(&ulog->lock); /* initialize ulog_buffers */ - for (i = 0; i < ULOG_MAXNLGROUPS; i++) - setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer, i); + for (i = 0; i < ULOG_MAXNLGROUPS; i++) { + ulog->nlgroup[i] = i; + setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer, + (unsigned long)&ulog->nlgroup[i]); + } ulog->nflognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); if (!ulog->nflognl) -- cgit v1.2.1 From ab4eb3537e3f20b2a88467e1f708a136df6e0ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?YOSHIFUJI=20Hideaki=20/=20=E5=90=89=E8=97=A4=E8=8B=B1?= =?UTF-8?q?=E6=98=8E?= Date: Sat, 22 Jun 2013 11:13:13 +0900 Subject: ipv6: Process unicast packet with Router Alert by checking flag in skb. Router Alert option is marked in skb. Previously, IP6CB(skb)->ra was set to positive value for such packets. Since commit dd3332bf ("ipv6: Store Router Alert option in IP6CB directly."), IP6SKB_ROUTERALERT is set in IP6CB(skb)->flags, and the value of Router Alert option (in network byte order) is set to IP6CB(skb)->ra for such packets. Multicast forwarding path uses that flag and value, but unicast forwarding path does not use the flag and misuses IP6CB(skb)->ra value. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index dae1949019d7..95703ba2c084 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -381,9 +381,8 @@ int ip6_forward(struct sk_buff *skb) * cannot be fragmented, because there is no warranty * that different fragments will go along one path. --ANK */ - if (opt->ra) { - u8 *ptr = skb_network_header(skb) + opt->ra; - if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) + if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) { + if (ip6_call_ra_chain(skb, ntohs(opt->ra))) return 0; } -- cgit v1.2.1 From bd8a7036c06cf15779b31a5397d4afcb12be81ea Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 24 Jun 2013 06:26:00 -0700 Subject: gre: fix a possible skb leak commit 68c331631143 ("v4 GRE: Add TCP segmentation offload for GRE") added a possible skb leak, because it frees only the head of segment list, in case a skb_linearize() call fails. This patch adds a kfree_skb_list() helper to fix the bug. Signed-off-by: Eric Dumazet Cc: Pravin B Shelar Cc: Daniel Borkmann Signed-off-by: David S. Miller --- net/core/skbuff.c | 20 ++++++++++++-------- net/ipv4/gre.c | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cfd777bd6bd0..1c1738cc4538 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -483,15 +483,8 @@ EXPORT_SYMBOL(skb_add_rx_frag); static void skb_drop_list(struct sk_buff **listp) { - struct sk_buff *list = *listp; - + kfree_skb_list(*listp); *listp = NULL; - - do { - struct sk_buff *this = list; - list = list->next; - kfree_skb(this); - } while (list); } static inline void skb_drop_fraglist(struct sk_buff *skb) @@ -651,6 +644,17 @@ void kfree_skb(struct sk_buff *skb) } EXPORT_SYMBOL(kfree_skb); +void kfree_skb_list(struct sk_buff *segs) +{ + while (segs) { + struct sk_buff *next = segs->next; + + kfree_skb(segs); + segs = next; + } +} +EXPORT_SYMBOL(kfree_skb_list); + /** * skb_tx_error - report an sk_buff xmit error * @skb: buffer that triggered an error diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index b2e805af9b87..7856d1651d05 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -178,7 +178,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, err = __skb_linearize(skb); if (err) { - kfree_skb(segs); + kfree_skb_list(segs); segs = ERR_PTR(err); goto out; } -- cgit v1.2.1 From dc8482926e2b1006ed6962ac8388cb92aed4efc7 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 24 Jun 2013 21:42:40 +0200 Subject: ipv6: check return value of ipv6_get_lladdr We should check the return value of ipv6_get_lladdr in inet6_set_iftoken. A possible situation, which could leave ll_addr unassigned is, when the user removed her link-local address but a global scoped address was already set. In this case the interface would still be IF_READY and not dead. In that case the RS source address is some value from the stack. v2: Daniel Borkmann noted a small indent inconstancy; no semantic changes. Cc: Daniel Borkmann Acked-by: Daniel Borkmann Reviewed-by: Flavio Leitner Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 77b626136c23..4ab4c38958c6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4306,6 +4306,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) struct inet6_ifaddr *ifp; struct net_device *dev = idev->dev; bool update_rs = false; + struct in6_addr ll_addr; if (token == NULL) return -EINVAL; @@ -4325,11 +4326,9 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) write_unlock_bh(&idev->lock); - if (!idev->dead && (idev->if_flags & IF_READY)) { - struct in6_addr ll_addr; - - ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | - IFA_F_OPTIMISTIC); + if (!idev->dead && (idev->if_flags & IF_READY) && + !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | + IFA_F_OPTIMISTIC)) { /* If we're not ready, then normal ifup will take care * of this. Otherwise, we need to request our rs here. -- cgit v1.2.1 From 5dbe7c178d3f0a4634f088d9e729f1909b9ddcd1 Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Wed, 26 Jun 2013 17:23:42 +0200 Subject: net: fix kernel deadlock with interface rename and netdev name retrieval. When the kernel (compiled with CONFIG_PREEMPT=n) is performing the rename of a network interface, it can end up waiting for a workqueue to complete. If userland is able to invoke a SIOCGIFNAME ioctl or a SO_BINDTODEVICE getsockopt in between, the kernel will deadlock due to the fact that read_secklock_begin() will spin forever waiting for the writer process (the one doing the interface rename) to update the devnet_rename_seq sequence. This patch fixes the problem by adding a helper (netdev_get_name()) and using it in the code handling the SIOCGIFNAME ioctl and SO_BINDTODEVICE setsockopt. The netdev_get_name() helper uses raw_seqcount_begin() to avoid spinning forever, waiting for devnet_rename_seq->sequence to become even. cond_resched() is used in the contended case, before retrying the access to give the writer process a chance to finish. The use of raw_seqcount_begin() will incur some unneeded work in the reader process in the contended case, but this is better than deadlocking the system. Signed-off-by: Nicolas Schichan Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 34 ++++++++++++++++++++++++++++++++++ net/core/dev_ioctl.c | 19 ++++--------------- net/core/sock.c | 17 ++--------------- 3 files changed, 40 insertions(+), 30 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index fc1e289397f5..faebb398fb46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -791,6 +791,40 @@ struct net_device *dev_get_by_index(struct net *net, int ifindex) } EXPORT_SYMBOL(dev_get_by_index); +/** + * netdev_get_name - get a netdevice name, knowing its ifindex. + * @net: network namespace + * @name: a pointer to the buffer where the name will be stored. + * @ifindex: the ifindex of the interface to get the name from. + * + * The use of raw_seqcount_begin() and cond_resched() before + * retrying is required as we want to give the writers a chance + * to complete when CONFIG_PREEMPT is not set. + */ +int netdev_get_name(struct net *net, char *name, int ifindex) +{ + struct net_device *dev; + unsigned int seq; + +retry: + seq = raw_seqcount_begin(&devnet_rename_seq); + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, ifindex); + if (!dev) { + rcu_read_unlock(); + return -ENODEV; + } + + strcpy(name, dev->name); + rcu_read_unlock(); + if (read_seqcount_retry(&devnet_rename_seq, seq)) { + cond_resched(); + goto retry; + } + + return 0; +} + /** * dev_getbyhwaddr_rcu - find a device by its hardware address * @net: the applicable net namespace diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index 6cc0481faade..5b7d0e1d0664 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -19,9 +19,8 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) { - struct net_device *dev; struct ifreq ifr; - unsigned seq; + int error; /* * Fetch the caller's info block. @@ -30,19 +29,9 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) return -EFAULT; -retry: - seq = read_seqcount_begin(&devnet_rename_seq); - rcu_read_lock(); - dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex); - if (!dev) { - rcu_read_unlock(); - return -ENODEV; - } - - strcpy(ifr.ifr_name, dev->name); - rcu_read_unlock(); - if (read_seqcount_retry(&devnet_rename_seq, seq)) - goto retry; + error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex); + if (error) + return error; if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; diff --git a/net/core/sock.c b/net/core/sock.c index 88868a9d21da..d6d024cfaaaf 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -571,9 +571,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval, int ret = -ENOPROTOOPT; #ifdef CONFIG_NETDEVICES struct net *net = sock_net(sk); - struct net_device *dev; char devname[IFNAMSIZ]; - unsigned seq; if (sk->sk_bound_dev_if == 0) { len = 0; @@ -584,20 +582,9 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval, if (len < IFNAMSIZ) goto out; -retry: - seq = read_seqcount_begin(&devnet_rename_seq); - rcu_read_lock(); - dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if); - ret = -ENODEV; - if (!dev) { - rcu_read_unlock(); + ret = netdev_get_name(net, devname, sk->sk_bound_dev_if); + if (ret) goto out; - } - - strcpy(devname, dev->name); - rcu_read_unlock(); - if (read_seqcount_retry(&devnet_rename_seq, seq)) - goto retry; len = strlen(devname) + 1; -- cgit v1.2.1 From a963a37d384d71ad43b3e9e79d68d42fbe0901f3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 26 Jun 2013 04:15:07 -0700 Subject: ipv6: ip6_sk_dst_check() must not assume ipv6 dst It's possible to use AF_INET6 sockets and to connect to an IPv4 destination. After this, socket dst cache is a pointer to a rtable, not rt6_info. ip6_sk_dst_check() should check the socket dst cache is IPv6, or else various corruptions/crashes can happen. Dave Jones can reproduce immediate crash with trinity -q -l off -n -c sendmsg -c connect With help from Hannes Frederic Sowa Reported-by: Dave Jones Reported-by: Hannes Frederic Sowa Signed-off-by: Eric Dumazet Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 95703ba2c084..d5d20cde8d92 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -821,11 +821,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, const struct flowi6 *fl6) { struct ipv6_pinfo *np = inet6_sk(sk); - struct rt6_info *rt = (struct rt6_info *)dst; + struct rt6_info *rt; if (!dst) goto out; + if (dst->ops->family != AF_INET6) { + dst_release(dst); + return NULL; + } + + rt = (struct rt6_info *)dst; /* Yes, checking route validity in not connected * case is not very simple. Take into account, * that we do not support routing by source, TOS, -- cgit v1.2.1 From a5cc68f3d63306d0d288f31edfc2ae6ef8ecd887 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 26 Jun 2013 23:52:30 +0200 Subject: af_key: fix info leaks in notify messages key_notify_sa_flush() and key_notify_policy_flush() miss to initialize the sadb_msg_reserved member of the broadcasted message and thereby leak 2 bytes of heap memory to listeners. Fix that. Signed-off-by: Mathias Krause Cc: Steffen Klassert Cc: "David S. Miller" Cc: Herbert Xu Signed-off-by: David S. Miller --- net/key/af_key.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/key/af_key.c b/net/key/af_key.c index c5fbd7589681..9da862070dd8 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1710,6 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c) hdr->sadb_msg_version = PF_KEY_V2; hdr->sadb_msg_errno = (uint8_t) 0; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + hdr->sadb_msg_reserved = 0; pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); @@ -2699,6 +2700,7 @@ static int key_notify_policy_flush(const struct km_event *c) hdr->sadb_msg_errno = (uint8_t) 0; hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + hdr->sadb_msg_reserved = 0; pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); return 0; -- cgit v1.2.1