From 14d2f38df67fadee34625fcbd282ee22514c4846 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 15 May 2013 16:28:33 -0500 Subject: libceph: must hold mutex for reset_changed_osds() An osd client has a red-black tree describing its osds, and occasionally we would get crashes due to one of these trees tree becoming corrupt somehow. The problem turned out to be that reset_changed_osds() was being called without protection of the osd client request mutex. That function would call __reset_osd() for any osd that had changed, and __reset_osd() would call __remove_osd() for any osd with no outstanding requests, and finally __remove_osd() would remove the corresponding entry from the red-black tree. Thus, the tree was getting modified without having any lock protection, and was vulnerable to problems due to concurrent updates. This appears to be the only osd tree updating path that has this problem. It can be fairly easily fixed by moving the call up a few lines, to just before the request mutex gets dropped in kick_requests(). This resolves: http://tracker.ceph.com/issues/5043 Cc: stable@vger.kernel.org # 3.4+ Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index d5953b87918c..3a246a6cab47 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1675,13 +1675,13 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) __register_request(osdc, req); __unregister_linger_request(osdc, req); } + reset_changed_osds(osdc); mutex_unlock(&osdc->request_mutex); if (needmap) { dout("%d requests for down osds, need new map\n", needmap); ceph_monc_request_next_osdmap(&osdc->client->monc); } - reset_changed_osds(osdc); } -- cgit v1.2.3 From 6390460af8a672754dd6743f326515e98f52b2a7 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Mon, 20 May 2013 23:05:15 +0530 Subject: net/9p: Handle error in zero copy request correctly for 9p2000.u For zero copy request, error will be encoded in the user space buffer. So copy the error code correctly using copy_from_user. Here we use the extra bytes we allocate for zero copy request. If total error details are more than P9_ZC_HDR_SZ - 7 bytes, we return -EFAULT. The patch also avoid a memory allocation in the error path. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Eric Van Hensbergen --- net/9p/client.c | 55 ++++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'net') diff --git a/net/9p/client.c b/net/9p/client.c index 8eb75425e6e6..addc116cecf0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -562,36 +562,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, if (!p9_is_proto_dotl(c)) { /* Error is reported in string format */ - uint16_t len; - /* 7 = header size for RERROR, 2 is the size of string len; */ - int inline_len = in_hdrlen - (7 + 2); + int len; + /* 7 = header size for RERROR; */ + int inline_len = in_hdrlen - 7; - /* Read the size of error string */ - err = p9pdu_readf(req->rc, c->proto_version, "w", &len); - if (err) - goto out_err; - - ename = kmalloc(len + 1, GFP_NOFS); - if (!ename) { - err = -ENOMEM; + len = req->rc->size - req->rc->offset; + if (len > (P9_ZC_HDR_SZ - 7)) { + err = -EFAULT; goto out_err; } - if (len <= inline_len) { - /* We have error in protocol buffer itself */ - if (pdu_read(req->rc, ename, len)) { - err = -EFAULT; - goto out_free; - } - } else { - /* - * Part of the data is in user space buffer. - */ - if (pdu_read(req->rc, ename, inline_len)) { - err = -EFAULT; - goto out_free; - - } + ename = &req->rc->sdata[req->rc->offset]; + if (len > inline_len) { + /* We have error in external buffer */ if (kern_buf) { memcpy(ename + inline_len, uidata, len - inline_len); @@ -600,19 +583,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, uidata, len - inline_len); if (err) { err = -EFAULT; - goto out_free; + goto out_err; } } } - ename[len] = 0; - if (p9_is_proto_dotu(c)) { - /* For dotu we also have error code */ - err = p9pdu_readf(req->rc, - c->proto_version, "d", &ecode); - if (err) - goto out_free; + ename = NULL; + err = p9pdu_readf(req->rc, c->proto_version, "s?d", + &ename, &ecode); + if (err) + goto out_err; + + if (p9_is_proto_dotu(c)) err = -ecode; - } + if (!err || !IS_ERR_VALUE(err)) { err = p9_errstr2errno(ename, strlen(ename)); @@ -628,8 +611,6 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, } return err; -out_free: - kfree(ename); out_err: p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); return err; -- cgit v1.2.3 From 991a6b735ff47710769545b11e481bb140b2e6f7 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 1 Jun 2013 15:31:40 +0200 Subject: netfilter: nfnetlink_acct: fix incomplete dumping of objects Fix broken incomplete object dumping if the list of objects does not fit into one single netlink message. Reported-by: Gabriel Lazar Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_acct.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index dc3fd5d44464..c7b6d466a662 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -149,9 +149,12 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); list_for_each_entry_rcu(cur, &nfnl_acct_list, head) { - if (last && cur != last) - continue; + if (last) { + if (cur != last) + continue; + last = NULL; + } if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NFNL_MSG_TYPE(cb->nlh->nlmsg_type), -- cgit v1.2.3 From 37bc4f8dfa72fb43b84381abca39cfdbbc8ff2df Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 1 Jun 2013 15:36:02 +0200 Subject: netfilter: nfnetlink_cttimeout: fix incomplete dumping of objects Fix broken incomplete object dumping if the list of objects does not fit into one single netlink message. Reported-by: Gabriel Lazar Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_cttimeout.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 701c88a20fea..65074dfb9383 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -220,9 +220,12 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); list_for_each_entry_rcu(cur, &cttimeout_list, head) { - if (last && cur != last) - continue; + if (last) { + if (cur != last) + continue; + last = NULL; + } if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NFNL_MSG_TYPE(cb->nlh->nlmsg_type), -- cgit v1.2.3 From 409b545ac10d9548929557a75ad86540f59a2c83 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Tue, 4 Jun 2013 05:09:27 +0000 Subject: netfilter: xt_TCPMSS: Fix violation of RFC879 in absence of MSS option The clamp-mss-to-pmtu option of the xt_TCPMSS target can cause issues connecting to websites if there was no MSS option present in the original SYN packet from the client. In these cases, it may add a MSS higher than the default specified in RFC879. Fix this by never setting a value > 536 if no MSS option was specified by the client. This closes netfilter's bugzilla #662. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPMSS.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net') diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index a75240f0d42b..afaebc766933 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -125,6 +125,12 @@ tcpmss_mangle_packet(struct sk_buff *skb, skb_put(skb, TCPOLEN_MSS); + /* RFC 879 states that the default MSS is 536 without specific + * knowledge that the destination host is prepared to accept larger. + * Since no MSS was provided, we MUST NOT set a value > 536. + */ + newmss = min(newmss, (u16)536); + opt = (u_int8_t *)tcph + sizeof(struct tcphdr); memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); -- cgit v1.2.3 From 7b8dfe289fdde0066be343a3e0271ad6d7b6dbcf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 7 Jun 2013 18:42:00 +0200 Subject: netfilter: nfnetlink_queue: fix missing HW protocol Locally generated IPv4 and IPv6 traffic gets skb->protocol unset, thus passing zero. ip6tables -I OUTPUT -j NFQUEUE libmnl/examples/netfilter# ./nf-queue 0 & ping6 ::1 packet received (id=1 hw=0x0000 hook=3) ^^^^^^ Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_queue_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 4e27fa035814..5352b2d2d5bf 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -637,9 +637,6 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) if (queue->copy_mode == NFQNL_COPY_NONE) return -EINVAL; - if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(entry->skb)) - return __nfqnl_enqueue_packet(net, queue, entry); - skb = entry->skb; switch (entry->pf) { @@ -651,6 +648,9 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) break; } + if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb)) + return __nfqnl_enqueue_packet(net, queue, entry); + nf_bridge_adjust_skb_data(skb); segs = skb_gso_segment(skb, 0); /* Does not use PTR_ERR to limit the number of error codes that can be -- cgit v1.2.3 From 40edeff6e1c6f9a6f16536ae3375e3af9d648449 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 2 Jun 2013 11:15:55 +0000 Subject: net_sched: qdisc_get_rtab() must check data[] array qdisc_get_rtab() should check not only the keys in struct tc_ratespec, but also the full data[] array. "tc ... linklayer atm " only perturbs values in the 256 slots array. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_api.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 2b935e7cfe7b..281c1bded1f6 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -291,17 +291,18 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta { struct qdisc_rate_table *rtab; + if (tab == NULL || r->rate == 0 || r->cell_log == 0 || + nla_len(tab) != TC_RTAB_SIZE) + return NULL; + for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) { - if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) { + if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) && + !memcmp(&rtab->data, nla_data(tab), 1024)) { rtab->refcnt++; return rtab; } } - if (tab == NULL || r->rate == 0 || r->cell_log == 0 || - nla_len(tab) != TC_RTAB_SIZE) - return NULL; - rtab = kmalloc(sizeof(*rtab), GFP_KERNEL); if (rtab) { rtab->rate = *r; -- cgit v1.2.3 From ac16d1484efd5d2d9077c55453b1f8abff49fc18 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 28 May 2013 17:32:32 +0200 Subject: batman-adv: wait for rtnl in batadv_store_mesh_iface instead of failing if it is taken The rtnl_lock in batadv_store_mesh_iface has been converted to a rtnl_trylock some time ago to avoid a possible deadlock between rtnl and s_active on removal of the sysfs nodes. The behaviour introduced by that was quite confusing as it could lead to the sysfs store to fail, making batman-adv setup scripts unreliable. As recently the sysfs removal was postponed to a worker not running with the rtnl taken, the deadlock can't occur any more and it is safe to change the trylock back to a lock to make the sysfs store reliable again. Signed-off-by: Matthias Schiffer Reviewed-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/sysfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'net') diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 15a22efa9a67..929e304dacb2 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -582,10 +582,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj, (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) goto out; - if (!rtnl_trylock()) { - ret = -ERESTARTSYS; - goto out; - } + rtnl_lock(); if (status_tmp == BATADV_IF_NOT_IN_USE) { batadv_hardif_disable_interface(hard_iface, -- cgit v1.2.3 From 7c24bbbeab4159f924b65b1e94878e597b762714 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 23 May 2013 13:07:42 +0200 Subject: batman-adv: forward late OGMs from best next hop When a packet is received from another node first and later from the best next hop, this packet is dropped. However the first OGM was sent with the BATADV_NOT_BEST_NEXT_HOP flag and thus dropped by neighbors. The late OGM from the best neighbor is then dropped because it is a duplicate. If this situation happens constantly, a node might end up not forwarding the "valid" OGMs anymore, and nodes behind will starve from not getting valid OGMs. Fix this by refining the duplicate checking behaviour: The actions should depend on whether it was a duplicate for a neighbor only or for the originator. OGMs which are not duplicates for a specific neighbor will now be considered in batadv_iv_ogm_forward(), but only actually forwarded for the best next hop. Therefore, late OGMs from the best next hop are forwarded now and not dropped as duplicates anymore. Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bat_iv_ogm.c | 86 +++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 31 deletions(-) (limited to 'net') diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 071f288b77a8..f680ee101878 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -29,6 +29,21 @@ #include "bat_algo.h" #include "network-coding.h" +/** + * batadv_dup_status - duplicate status + * @BATADV_NO_DUP: the packet is a duplicate + * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the + * neighbor) + * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor + * @BATADV_PROTECTED: originator is currently protected (after reboot) + */ +enum batadv_dup_status { + BATADV_NO_DUP = 0, + BATADV_ORIG_DUP, + BATADV_NEIGH_DUP, + BATADV_PROTECTED, +}; + static struct batadv_neigh_node * batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, @@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, const struct batadv_ogm_packet *batadv_ogm_packet, struct batadv_hard_iface *if_incoming, const unsigned char *tt_buff, - int is_duplicate) + enum batadv_dup_status dup_status) { struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; struct batadv_neigh_node *router = NULL; @@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, continue; } - if (is_duplicate) + if (dup_status != BATADV_NO_DUP) continue; spin_lock_bh(&tmp_neigh_node->lq_update_lock); @@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); spin_unlock_bh(&neigh_node->lq_update_lock); - if (!is_duplicate) { + if (dup_status == BATADV_NO_DUP) { orig_node->last_ttl = batadv_ogm_packet->header.ttl; neigh_node->last_ttl = batadv_ogm_packet->header.ttl; } @@ -902,15 +917,16 @@ out: return ret; } -/* processes a batman packet for all interfaces, adjusts the sequence number and - * finds out whether it is a duplicate. - * returns: - * 1 the packet is a duplicate - * 0 the packet has not yet been received - * -1 the packet is old and has been received while the seqno window - * was protected. Caller should drop it. +/** + * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces, + * adjust the sequence number and find out whether it is a duplicate + * @ethhdr: ethernet header of the packet + * @batadv_ogm_packet: OGM packet to be considered + * @if_incoming: interface on which the OGM packet was received + * + * Returns duplicate status as enum batadv_dup_status */ -static int +static enum batadv_dup_status batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, const struct batadv_ogm_packet *batadv_ogm_packet, const struct batadv_hard_iface *if_incoming) @@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct batadv_orig_node *orig_node; struct batadv_neigh_node *tmp_neigh_node; - int is_duplicate = 0; + int is_dup; int32_t seq_diff; int need_update = 0; - int set_mark, ret = -1; + int set_mark; + enum batadv_dup_status ret = BATADV_NO_DUP; uint32_t seqno = ntohl(batadv_ogm_packet->seqno); uint8_t *neigh_addr; uint8_t packet_count; orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); if (!orig_node) - return 0; + return BATADV_NO_DUP; spin_lock_bh(&orig_node->ogm_cnt_lock); seq_diff = seqno - orig_node->last_real_seqno; @@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, /* signalize caller that the packet is to be dropped. */ if (!hlist_empty(&orig_node->neigh_list) && batadv_window_protected(bat_priv, seq_diff, - &orig_node->batman_seqno_reset)) + &orig_node->batman_seqno_reset)) { + ret = BATADV_PROTECTED; goto out; + } rcu_read_lock(); hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { - is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits, - orig_node->last_real_seqno, - seqno); - neigh_addr = tmp_neigh_node->addr; + is_dup = batadv_test_bit(tmp_neigh_node->real_bits, + orig_node->last_real_seqno, + seqno); + if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && - tmp_neigh_node->if_incoming == if_incoming) + tmp_neigh_node->if_incoming == if_incoming) { set_mark = 1; - else + if (is_dup) + ret = BATADV_NEIGH_DUP; + } else { set_mark = 0; + if (is_dup && (ret != BATADV_NEIGH_DUP)) + ret = BATADV_ORIG_DUP; + } /* if the window moved, set the update flag. */ need_update |= batadv_bit_get_packet(bat_priv, @@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, orig_node->last_real_seqno = seqno; } - ret = is_duplicate; - out: spin_unlock_bh(&orig_node->ogm_cnt_lock); batadv_orig_node_free_ref(orig_node); @@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, int is_broadcast = 0, is_bidirect; bool is_single_hop_neigh = false; bool is_from_best_next_hop = false; - int is_duplicate, sameseq, simlar_ttl; + int sameseq, similar_ttl; + enum batadv_dup_status dup_status; uint32_t if_incoming_seqno; uint8_t *prev_sender; @@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, if (!orig_node) return; - is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, - if_incoming); + dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, + if_incoming); - if (is_duplicate == -1) { + if (dup_status == BATADV_PROTECTED) { batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Drop packet: packet within seqno protection time (sender: %pM)\n", ethhdr->h_source); @@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, * seqno and similar ttl as the non-duplicate */ sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); - simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; - if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl))) + similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; + if (is_bidirect && ((dup_status == BATADV_NO_DUP) || + (sameseq && similar_ttl))) batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, batadv_ogm_packet, if_incoming, - tt_buff, is_duplicate); + tt_buff, dup_status); /* is single hop (direct) neighbor */ if (is_single_hop_neigh) { @@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, goto out_neigh; } - if (is_duplicate) { + if (dup_status == BATADV_NEIGH_DUP) { batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Drop packet: duplicate packet received\n"); goto out_neigh; -- cgit v1.2.3 From d5b4c93e67b0b1291aa8e2aaf694e40afc3412d0 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Fri, 7 Jun 2013 16:52:05 +0200 Subject: batman-adv: Don't handle address updates when bla is disabled The bridge loop avoidance has a hook to handle address updates of the originator. These should not be handled when bridge loop avoidance is disabled - it might send some bridge loop avoidance packets which should not appear if bla is disabled. Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 379061c72549..de27b3175cfd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1067,6 +1067,10 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); bat_priv->bla.claim_dest.group = group; + /* purge everything when bridge loop avoidance is turned off */ + if (!atomic_read(&bat_priv->bridge_loop_avoidance)) + oldif = NULL; + if (!oldif) { batadv_bla_purge_claims(bat_priv, NULL, 1); batadv_bla_purge_backbone_gw(bat_priv, 1); -- cgit v1.2.3 From a8241c63517ec0b900695daa9003cddc41c536a1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 3 Jun 2013 12:00:49 +0300 Subject: ipvs: info leak in __ip_vs_get_dest_entries() The entry struct has a 2 byte hole after ->port and another 4 byte hole after ->stats.outpkts. You must have CAP_NET_ADMIN in your namespace to hit this information leak. Signed-off-by: Dan Carpenter Acked-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5b142fb16480..9e6c2a075a4c 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2542,6 +2542,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, struct ip_vs_dest *dest; struct ip_vs_dest_entry entry; + memset(&entry, 0, sizeof(entry)); list_for_each_entry(dest, &svc->destinations, n_list) { if (count >= get->num_dests) break; -- cgit v1.2.3 From ed82c437320c48a4032492f4a55a7e2c934158b6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 11 Jun 2013 01:51:31 +0200 Subject: netfilter: xt_TCPOPTSTRIP: don't use tcp_hdr() In (bc6bcb5 netfilter: xt_TCPOPTSTRIP: fix possible mangling beyond packet boundary), the use of tcp_hdr was introduced. However, we cannot assume that skb->transport_header is set for non-local packets. Cc: Florian Westphal Reported-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPOPTSTRIP.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 1eb1a44bfd3d..b68fa191710f 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c @@ -48,11 +48,13 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, return NF_DROP; len = skb->len - tcphoff; - if (len < (int)sizeof(struct tcphdr) || - tcp_hdr(skb)->doff * 4 > len) + if (len < (int)sizeof(struct tcphdr)) return NF_DROP; tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + if (tcph->doff * 4 > len) + return NF_DROP; + opt = (u_int8_t *)tcph; /* -- cgit v1.2.3 From ed13998c319b050fc9abdb73915859dfdbe1fb38 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 5 Jun 2013 15:30:55 +0200 Subject: sock_diag: fix filter code sent to userspace Filters need to be translated to real BPF code for userland, like SO_GETFILTER. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/core/filter.c | 2 +- net/core/sock_diag.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/filter.c b/net/core/filter.c index dad2a178f9f8..6438f29ff266 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -778,7 +778,7 @@ int sk_detach_filter(struct sock *sk) } EXPORT_SYMBOL_GPL(sk_detach_filter); -static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) +void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) { static const u16 decodes[] = { [BPF_S_ALU_ADD_K] = BPF_ALU|BPF_ADD|BPF_K, diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index d5bef0b0f639..a0e9cf6379de 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -73,8 +73,13 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, goto out; } - if (filter) - memcpy(nla_data(attr), filter->insns, len); + if (filter) { + struct sock_filter *fb = (struct sock_filter *)nla_data(attr); + int i; + + for (i = 0; i < filter->len; i++, fb++) + sk_decode_filter(&filter->insns[i], fb); + } out: rcu_read_unlock(); -- cgit v1.2.3 From 1abd165ed757db1afdefaac0a4bc8a70f97d258c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 6 Jun 2013 15:53:47 +0200 Subject: net: sctp: fix NULL pointer dereference in socket destruction While stress testing sctp sockets, I hit the following panic: BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 IP: [] sctp_endpoint_free+0xe/0x40 [sctp] PGD 7cead067 PUD 7ce76067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: sctp(F) libcrc32c(F) [...] CPU: 7 PID: 2950 Comm: acc Tainted: GF 3.10.0-rc2+ #1 Hardware name: Dell Inc. PowerEdge T410/0H19HD, BIOS 1.6.3 02/01/2011 task: ffff88007ce0e0c0 ti: ffff88007b568000 task.ti: ffff88007b568000 RIP: 0010:[] [] sctp_endpoint_free+0xe/0x40 [sctp] RSP: 0018:ffff88007b569e08 EFLAGS: 00010292 RAX: 0000000000000000 RBX: ffff88007db78a00 RCX: dead000000200200 RDX: ffffffffa049fdb0 RSI: ffff8800379baf38 RDI: 0000000000000000 RBP: ffff88007b569e18 R08: ffff88007c230da0 R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff880077990d00 R14: 0000000000000084 R15: ffff88007db78a00 FS: 00007fc18ab61700(0000) GS:ffff88007fc60000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000020 CR3: 000000007cf9d000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffff88007b569e38 ffff88007db78a00 ffff88007b569e38 ffffffffa049fded ffffffff81abf0c0 ffff88007db78a00 ffff88007b569e58 ffffffff8145b60e 0000000000000000 0000000000000000 ffff88007b569eb8 ffffffff814df36e Call Trace: [] sctp_destroy_sock+0x3d/0x80 [sctp] [] sk_common_release+0x1e/0xf0 [] inet_create+0x2ae/0x350 [] __sock_create+0x11f/0x240 [] sock_create+0x30/0x40 [] SyS_socket+0x4c/0xc0 [] ? do_page_fault+0xe/0x10 [] ? page_fault+0x22/0x30 [] system_call_fastpath+0x16/0x1b Code: 0c c9 c3 66 2e 0f 1f 84 00 00 00 00 00 e8 fb fe ff ff c9 c3 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 <48> 8b 47 20 48 89 fb c6 47 1c 01 c6 40 12 07 e8 9e 68 01 00 48 RIP [] sctp_endpoint_free+0xe/0x40 [sctp] RSP CR2: 0000000000000020 ---[ end trace e0d71ec1108c1dd9 ]--- I did not hit this with the lksctp-tools functional tests, but with a small, multi-threaded test program, that heavily allocates, binds, listens and waits in accept on sctp sockets, and then randomly kills some of them (no need for an actual client in this case to hit this). Then, again, allocating, binding, etc, and then killing child processes. This panic then only occurs when ``echo 1 > /proc/sys/net/sctp/auth_enable'' is set. The cause for that is actually very simple: in sctp_endpoint_init() we enter the path of sctp_auth_init_hmacs(). There, we try to allocate our crypto transforms through crypto_alloc_hash(). In our scenario, it then can happen that crypto_alloc_hash() fails with -EINTR from crypto_larval_wait(), thus we bail out and release the socket via sk_common_release(), sctp_destroy_sock() and hit the NULL pointer dereference as soon as we try to access members in the endpoint during sctp_endpoint_free(), since endpoint at that time is still NULL. Now, if we have that case, we do not need to do any cleanup work and just leave the destruction handler. Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f631c5ff4dbf..6abb1caf9836 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4003,6 +4003,12 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) /* Release our hold on the endpoint. */ sp = sctp_sk(sk); + /* This could happen during socket init, thus we bail out + * early, since the rest of the below is not setup either. + */ + if (sp->ep == NULL) + return; + if (sp->do_auto_asconf) { sp->do_auto_asconf = 0; list_del(&sp->auto_asconf_list); -- cgit v1.2.3 From 7cdbac71f911494aa7d0343be23c092ca84a5ed4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 11 Jun 2013 02:52:47 -0700 Subject: netlink: fix error propagation in netlink_mmap() Return the error if something went wrong instead of unconditionally returning 0. Signed-off-by: Patrick McHardy 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 d0b3dd60d386..57ee84d21470 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -371,7 +371,7 @@ static int netlink_mmap(struct file *file, struct socket *sock, err = 0; out: mutex_unlock(&nlk->pg_vec_lock); - return 0; + return err; } static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr) -- cgit v1.2.3 From 35d865afbbdf79e492f7d61df92b1a9e1d93d26f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 28 May 2013 10:54:03 +0200 Subject: mac80211: work around broken APs not including HT info There are some APs, notably 2G/3G/4G Wifi routers, specifically the "Onda PN51T", "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile branded device [1] that erroneously don't include all the needed information in (re)association response frames. Work around this by assuming the information is the same as it was in the beacon or probe response and using the data from there instead. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=58881. [1] https://bbs.archlinux.org/viewtopic.php?pid=1277305 Note that this requires marking the first ieee802_11_parse_elems() argument const, otherwise we'd get a compiler warning. Cc: stable@vger.kernel.org Reported-and-tested-by: Michal Zajac Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 5 +-- net/mac80211/mlme.c | 87 ++++++++++++++++++++++++++++++++++++++++++---- net/mac80211/util.c | 4 +-- 3 files changed, 85 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 44be28cfc6c4..9ca8e3278cc0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1497,10 +1497,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb_tid(sdata, skb, 7); } -u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, +u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems, u64 filter, u32 crc); -static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, +static inline void ieee802_11_parse_elems(const u8 *start, size_t len, + bool action, struct ieee802_11_elems *elems) { ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a8c2130c8ba4..741448b30825 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2522,8 +2522,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, u16 capab_info, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; + const struct cfg80211_bss_ies *bss_ies = NULL; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; u32 changed = 0; int err; + bool ret; /* AssocResp and ReassocResp have identical structure */ @@ -2554,6 +2557,69 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ifmgd->aid = aid; + /* + * Some APs are erroneously not including some information in their + * (re)association response frames. Try to recover by using the data + * from the beacon or probe response. This seems to afflict mobile + * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", + * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. + */ + if ((assoc_data->wmm && !elems.wmm_param) || + (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && + (!elems.ht_cap_elem || !elems.ht_operation)) || + (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && + (!elems.vht_cap_elem || !elems.vht_operation))) { + const struct cfg80211_bss_ies *ies; + struct ieee802_11_elems bss_elems; + + rcu_read_lock(); + ies = rcu_dereference(cbss->ies); + if (ies) + bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, + GFP_ATOMIC); + rcu_read_unlock(); + if (!bss_ies) + return false; + + ieee802_11_parse_elems(bss_ies->data, bss_ies->len, + false, &bss_elems); + if (assoc_data->wmm && + !elems.wmm_param && bss_elems.wmm_param) { + elems.wmm_param = bss_elems.wmm_param; + sdata_info(sdata, + "AP bug: WMM param missing from AssocResp\n"); + } + + /* + * Also check if we requested HT/VHT, otherwise the AP doesn't + * have to include the IEs in the (re)association response. + */ + if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { + elems.ht_cap_elem = bss_elems.ht_cap_elem; + sdata_info(sdata, + "AP bug: HT capability missing from AssocResp\n"); + } + if (!elems.ht_operation && bss_elems.ht_operation && + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { + elems.ht_operation = bss_elems.ht_operation; + sdata_info(sdata, + "AP bug: HT operation missing from AssocResp\n"); + } + if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { + elems.vht_cap_elem = bss_elems.vht_cap_elem; + sdata_info(sdata, + "AP bug: VHT capa missing from AssocResp\n"); + } + if (!elems.vht_operation && bss_elems.vht_operation && + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { + elems.vht_operation = bss_elems.vht_operation; + sdata_info(sdata, + "AP bug: VHT operation missing from AssocResp\n"); + } + } + /* * We previously checked these in the beacon/probe response, so * they should be present here. This is just a safety net. @@ -2561,15 +2627,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { sdata_info(sdata, - "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); - return false; + "HT AP is missing WMM params or HT capability/operation\n"); + ret = false; + goto out; } if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && (!elems.vht_cap_elem || !elems.vht_operation)) { sdata_info(sdata, - "VHT AP is missing VHT capability/operation in AssocResp\n"); - return false; + "VHT AP is missing VHT capability/operation\n"); + ret = false; + goto out; } mutex_lock(&sdata->local->sta_mtx); @@ -2580,7 +2648,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(sdata, cbss->bssid); if (WARN_ON(!sta)) { mutex_unlock(&sdata->local->sta_mtx); - return false; + ret = false; + goto out; } sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; @@ -2633,7 +2702,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta->sta.addr); WARN_ON(__sta_info_destroy(sta)); mutex_unlock(&sdata->local->sta_mtx); - return false; + ret = false; + goto out; } mutex_unlock(&sdata->local->sta_mtx); @@ -2673,7 +2743,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); ieee80211_sta_reset_beacon_monitor(sdata); - return true; + ret = true; + out: + kfree(bss_ies); + return ret; } static enum rx_mgmt_action __must_check diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 27e07150eb46..72e6292955bb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -661,12 +661,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_queue_delayed_work); -u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, +u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems, u64 filter, u32 crc) { size_t left = len; - u8 *pos = start; + const u8 *pos = start; bool calc_crc = filter != 0; DECLARE_BITMAP(seen_elems, 256); const u8 *ie; -- cgit v1.2.3 From a6b368f6caec2c897a2ac98c5c359cab9c35dea5 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 11 Jun 2013 10:44:39 +0200 Subject: mac80211: abort CAC in stop_ap() When a CAC is running and stop_ap is called (e.g. when hostapd is killed while performing CAC), the CAC must be aborted immediately. Otherwise ieee80211_stop_ap() will try to stop it when it's too late - wdev->channel is already NULL and the abort event can not be generated. Signed-off-by: Simon Wunderlich Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1a89c80e6407..4fdb306e42e0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1057,6 +1057,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + if (sdata->wdev.cac_started) { + cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); + cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, + GFP_KERNEL); + } + drv_stop_ap(sdata->local, sdata); /* free all potentially still buffered bcast frames */ -- cgit v1.2.3 From 795d855d56c6d172f50a974f603ba923ac93ee76 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 11 Jun 2013 10:44:40 +0200 Subject: mac80211: Fix rate control mask matching call The order of parameters was mixed up, introduced in commit "mac80211: improve the rate control API" Cc: Felix Fietkau Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- net/mac80211/rate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index d3f414fe67e0..a02bef35b134 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, if (rates[i].idx < 0) break; - rate_idx_match_mask(&rates[i], sband, mask, chan_width, + rate_idx_match_mask(&rates[i], sband, chan_width, mask, mcs_mask); } } -- cgit v1.2.3 From 70d19f805f8c047fc0a28dec9306b3773971c8d9 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Wed, 12 Jun 2013 10:44:51 +0200 Subject: netfilter: xt_TCPMSS: Fix IPv6 default MSS too As a followup to commit 409b545a ("netfilter: xt_TCPMSS: Fix violation of RFC879 in absence of MSS option"), John Heffner points out that IPv6 has a higher MTU than IPv4, and thus a higher minimum MSS. Update TCPMSS target to account for this, and update RFC comment. While at it, point to more recent reference RFC1122 instead of RFC879. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPMSS.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index afaebc766933..6640a224f9fb 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -45,11 +45,12 @@ optlen(const u_int8_t *opt, unsigned int offset) static int tcpmss_mangle_packet(struct sk_buff *skb, - const struct xt_tcpmss_info *info, + const struct xt_action_param *par, unsigned int in_mtu, unsigned int tcphoff, unsigned int minlen) { + const struct xt_tcpmss_info *info = par->targinfo; struct tcphdr *tcph; unsigned int tcplen, i; __be16 oldval; @@ -125,11 +126,17 @@ tcpmss_mangle_packet(struct sk_buff *skb, skb_put(skb, TCPOLEN_MSS); - /* RFC 879 states that the default MSS is 536 without specific - * knowledge that the destination host is prepared to accept larger. - * Since no MSS was provided, we MUST NOT set a value > 536. + /* + * IPv4: RFC 1122 states "If an MSS option is not received at + * connection setup, TCP MUST assume a default send MSS of 536". + * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum + * length IPv6 header of 60, ergo the default MSS value is 1220 + * Since no MSS was provided, we must use the default values */ - newmss = min(newmss, (u16)536); + if (par->family == NFPROTO_IPV4) + newmss = min(newmss, (u16)536); + else + newmss = min(newmss, (u16)1220); opt = (u_int8_t *)tcph + sizeof(struct tcphdr); memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); @@ -188,7 +195,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) __be16 newlen; int ret; - ret = tcpmss_mangle_packet(skb, par->targinfo, + ret = tcpmss_mangle_packet(skb, par, tcpmss_reverse_mtu(skb, PF_INET), iph->ihl * 4, sizeof(*iph) + sizeof(struct tcphdr)); @@ -217,7 +224,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); if (tcphoff < 0) return NF_DROP; - ret = tcpmss_mangle_packet(skb, par->targinfo, + ret = tcpmss_mangle_packet(skb, par, tcpmss_reverse_mtu(skb, PF_INET6), tcphoff, sizeof(*ipv6h) + sizeof(struct tcphdr)); -- cgit v1.2.3 From b396966c4688522863572927cb30aa874b3ec504 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Wed, 12 Jun 2013 10:58:20 +0200 Subject: netfilter: xt_TCPMSS: Fix missing fragmentation handling Similar to commit bc6bcb59 ("netfilter: xt_TCPOPTSTRIP: fix possible mangling beyond packet boundary"), add safe fragment handling to xt_TCPMSS. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPMSS.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 6640a224f9fb..7011c71646f0 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -57,6 +57,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, u16 newmss; u8 *opt; + /* This is a fragment, no TCP header is available */ + if (par->fragoff != 0) + return XT_CONTINUE; + if (!skb_make_writable(skb, skb->len)) return -1; -- cgit v1.2.3 From 757aee0f7177b7c7528aa0c120fc131aca8bf641 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 24 Apr 2013 13:05:32 +0300 Subject: Bluetooth: Fix checks for LE support on LE-only controllers LE-only controllers do not support extended features so any kind of host feature bit checks do not make sense for them. This patch fixes code used for both single-mode (LE-only) and dual-mode (BR/EDR/LE) to use the HCI_LE_ENABLED flag instead of the "Host LE supported" feature bit for LE support tests. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- net/bluetooth/mgmt.c | 2 +- net/bluetooth/smp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 35fef22703e9..5e93b24d01fd 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2700,7 +2700,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, break; case DISCOV_TYPE_LE: - if (!lmp_host_le_capable(hdev)) { + if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, MGMT_STATUS_NOT_SUPPORTED); mgmt_pending_remove(cmd); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index b2296d3857a0..b5562abdd6e0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -770,7 +770,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); - if (!lmp_host_le_capable(hcon->hdev)) + if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) return 1; if (sec_level == BT_SECURITY_LOW) @@ -851,7 +851,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) __u8 reason; int err = 0; - if (!lmp_host_le_capable(conn->hcon->hdev)) { + if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) { err = -ENOTSUPP; reason = SMP_PAIRING_NOTSUPP; goto done; -- cgit v1.2.3 From cb3b3152b2f5939d67005cff841a1ca748b19888 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 28 May 2013 13:46:30 +0300 Subject: Bluetooth: Fix missing length checks for L2CAP signalling PDUs There has been code in place to check that the L2CAP length header matches the amount of data received, but many PDU handlers have not been checking that the data received actually matches that expected by the specific PDU. This patch adds passing the length header to the specific handler functions and ensures that those functions fail cleanly in the case of an incorrect amount of data. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- net/bluetooth/l2cap_core.c | 70 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 18 deletions(-) (limited to 'net') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a76d1ac0321b..24bee07ee4ce 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3677,10 +3677,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) } static inline int l2cap_command_rej(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; + if (cmd_len < sizeof(*rej)) + return -EPROTO; + if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) return 0; @@ -3829,11 +3833,14 @@ sendresp: } static int l2cap_connect_req(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { struct hci_dev *hdev = conn->hcon->hdev; struct hci_conn *hcon = conn->hcon; + if (cmd_len < sizeof(struct l2cap_conn_req)) + return -EPROTO; + hci_dev_lock(hdev); if (test_bit(HCI_MGMT, &hdev->dev_flags) && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) @@ -3847,7 +3854,8 @@ static int l2cap_connect_req(struct l2cap_conn *conn, } static int l2cap_connect_create_rsp(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; @@ -3855,6 +3863,9 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, u8 req[128]; int err; + if (cmd_len < sizeof(*rsp)) + return -EPROTO; + scid = __le16_to_cpu(rsp->scid); dcid = __le16_to_cpu(rsp->dcid); result = __le16_to_cpu(rsp->result); @@ -3952,6 +3963,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_chan *chan; int len, err = 0; + if (cmd_len < sizeof(*req)) + return -EPROTO; + dcid = __le16_to_cpu(req->dcid); flags = __le16_to_cpu(req->flags); @@ -3975,7 +3989,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); - if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { + if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_REJECT, flags), rsp); @@ -4053,14 +4067,18 @@ unlock: } static inline int l2cap_config_rsp(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; struct l2cap_chan *chan; - int len = le16_to_cpu(cmd->len) - sizeof(*rsp); + int len = cmd_len - sizeof(*rsp); int err = 0; + if (cmd_len < sizeof(*rsp)) + return -EPROTO; + scid = __le16_to_cpu(rsp->scid); flags = __le16_to_cpu(rsp->flags); result = __le16_to_cpu(rsp->result); @@ -4161,7 +4179,8 @@ done: } static inline int l2cap_disconnect_req(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; struct l2cap_disconn_rsp rsp; @@ -4169,6 +4188,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_chan *chan; struct sock *sk; + if (cmd_len != sizeof(*req)) + return -EPROTO; + scid = __le16_to_cpu(req->scid); dcid = __le16_to_cpu(req->dcid); @@ -4208,12 +4230,16 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, } static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; struct l2cap_chan *chan; + if (cmd_len != sizeof(*rsp)) + return -EPROTO; + scid = __le16_to_cpu(rsp->scid); dcid = __le16_to_cpu(rsp->dcid); @@ -4243,11 +4269,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, } static inline int l2cap_information_req(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_info_req *req = (struct l2cap_info_req *) data; u16 type; + if (cmd_len != sizeof(*req)) + return -EPROTO; + type = __le16_to_cpu(req->type); BT_DBG("type 0x%4.4x", type); @@ -4294,11 +4324,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, } static inline int l2cap_information_rsp(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, u8 *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; u16 type, result; + if (cmd_len != sizeof(*rsp)) + return -EPROTO; + type = __le16_to_cpu(rsp->type); result = __le16_to_cpu(rsp->result); @@ -5164,16 +5198,16 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, switch (cmd->code) { case L2CAP_COMMAND_REJ: - l2cap_command_rej(conn, cmd, data); + l2cap_command_rej(conn, cmd, cmd_len, data); break; case L2CAP_CONN_REQ: - err = l2cap_connect_req(conn, cmd, data); + err = l2cap_connect_req(conn, cmd, cmd_len, data); break; case L2CAP_CONN_RSP: case L2CAP_CREATE_CHAN_RSP: - err = l2cap_connect_create_rsp(conn, cmd, data); + err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data); break; case L2CAP_CONF_REQ: @@ -5181,15 +5215,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, break; case L2CAP_CONF_RSP: - err = l2cap_config_rsp(conn, cmd, data); + err = l2cap_config_rsp(conn, cmd, cmd_len, data); break; case L2CAP_DISCONN_REQ: - err = l2cap_disconnect_req(conn, cmd, data); + err = l2cap_disconnect_req(conn, cmd, cmd_len, data); break; case L2CAP_DISCONN_RSP: - err = l2cap_disconnect_rsp(conn, cmd, data); + err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data); break; case L2CAP_ECHO_REQ: @@ -5200,11 +5234,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, break; case L2CAP_INFO_REQ: - err = l2cap_information_req(conn, cmd, data); + err = l2cap_information_req(conn, cmd, cmd_len, data); break; case L2CAP_INFO_RSP: - err = l2cap_information_rsp(conn, cmd, data); + err = l2cap_information_rsp(conn, cmd, cmd_len, data); break; case L2CAP_CREATE_CHAN_REQ: -- cgit v1.2.3 From 96570ffcca0b872dc8626e97569d2697f374d868 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 29 May 2013 09:51:29 +0300 Subject: Bluetooth: Fix mgmt handling of power on failures If hci_dev_open fails we need to ensure that the corresponding mgmt_set_powered command gets an appropriate response. This patch fixes the missing response by adding a new mgmt_set_powered_failed function that's used to indicate a power on failure to mgmt. Since a situation with the device being rfkilled may require special handling in user space the patch uses a new dedicated mgmt status code for this. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- net/bluetooth/hci_core.c | 6 +++++- net/bluetooth/mgmt.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 33843c5c4939..d817c932d634 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1555,11 +1555,15 @@ static const struct rfkill_ops hci_rfkill_ops = { static void hci_power_on(struct work_struct *work) { struct hci_dev *hdev = container_of(work, struct hci_dev, power_on); + int err; BT_DBG("%s", hdev->name); - if (hci_dev_open(hdev->id) < 0) + err = hci_dev_open(hdev->id); + if (err < 0) { + mgmt_set_powered_failed(hdev, err); return; + } if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) queue_delayed_work(hdev->req_workqueue, &hdev->power_off, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 5e93b24d01fd..f8ecbc70293d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3418,6 +3418,27 @@ new_settings: return err; } +int mgmt_set_powered_failed(struct hci_dev *hdev, int err) +{ + struct pending_cmd *cmd; + u8 status; + + cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); + if (!cmd) + return -ENOENT; + + if (err == -ERFKILL) + status = MGMT_STATUS_RFKILLED; + else + status = MGMT_STATUS_FAILED; + + err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); + + mgmt_pending_remove(cmd); + + return err; +} + int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) { struct cmd_lookup match = { NULL, hdev }; -- cgit v1.2.3 From 2dc85bf323515e59e15dfa858d1472bb25cad0fe Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 12 Jun 2013 16:02:27 +0200 Subject: packet: packet_getname_spkt: make sure string is always 0-terminated uaddr->sa_data is exactly of size 14, which is hard-coded here and passed as a size argument to strncpy(). A device name can be of size IFNAMSIZ (== 16), meaning we might leave the destination string unterminated. Thus, use strlcpy() and also sizeof() while we're at it. We need to memset the data area beforehand, since strlcpy does not padd the remaining buffer with zeroes for user space, so that we do not possibly leak anything. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/packet/af_packet.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8ec1bca7f859..20a1bd0e6549 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2851,12 +2851,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, return -EOPNOTSUPP; uaddr->sa_family = AF_PACKET; + memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data)); rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); if (dev) - strncpy(uaddr->sa_data, dev->name, 14); - else - memset(uaddr->sa_data, 0, 14); + strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data)); rcu_read_unlock(); *uaddr_len = sizeof(*uaddr); -- cgit v1.2.3 From 55b92b7a11690bc377b5d373872a6b650ae88e64 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 12 Jun 2013 16:07:23 +0200 Subject: l2tp: Fix PPP header erasure and memory leak Copy user data after PPP framing header. This prevents erasure of the added PPP header and avoids leaking two bytes of uninitialised memory at the end of skb's data buffer. Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- net/l2tp/l2tp_ppp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 637a341c1e2d..681c626068b4 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -346,12 +346,12 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh skb_put(skb, 2); /* Copy user data into skb */ - error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); + error = memcpy_fromiovec(skb_put(skb, total_len), m->msg_iov, + total_len); if (error < 0) { kfree_skb(skb); goto error_put_sess_tun; } - skb_put(skb, total_len); l2tp_xmit_skb(session, skb, session->hdr_len); -- cgit v1.2.3 From a6f79d0f26704214b5b702bbac525cb72997f984 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 12 Jun 2013 16:07:36 +0200 Subject: l2tp: Fix sendmsg() return value PPPoL2TP sockets should comply with the standard send*() return values (i.e. return number of bytes sent instead of 0 upon success). Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- net/l2tp/l2tp_ppp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 681c626068b4..8dec6876dc50 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -358,7 +358,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh sock_put(ps->tunnel_sock); sock_put(sk); - return error; + return total_len; error_put_sess_tun: sock_put(ps->tunnel_sock); -- cgit v1.2.3 From baafc77b32f647daa7c45825f7af8cdd55d00817 Mon Sep 17 00:00:00 2001 From: Saurabh Mohan Date: Mon, 10 Jun 2013 17:45:10 -0700 Subject: net/ipv4: ip_vti clear skb cb before tunneling. If users apply shaper to vti tunnel then it will cause a kernel crash. The problem seems to be due to the vti_tunnel_xmit function not clearing skb->opt field before passing the packet to xfrm tunneling code. Signed-off-by: Saurabh Mohan Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv4/ip_vti.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 9d2bdb2c1d3f..c118f6b576bb 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -361,8 +361,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) tunnel->err_count = 0; } - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | - IPSKB_REROUTED); + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); skb_dst_drop(skb); skb_dst_set(skb, &rt->dst); nf_reset(skb); -- cgit v1.2.3 From d3b6f6141831b6e2d414edea6cc7af5b9bc6fac2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 7 Jun 2013 13:26:05 -0700 Subject: ip_tunnel: remove __net_init/exit from exported functions If CONFIG_NET_NS is not set then __net_init is the same as __init and __net_exit is the same as __exit. These functions will be removed from memory after the module loads or is removed. Functions that are exported for use by other functions should never be labeled for removal. Bug introduced by commit c54419321455631079c ("GRE: Refactor GRE tunneling code.") Reported-by: Steinar H. Gunderson Signed-off-by: Steven Rostedt Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index be2f8da0ae8e..7fa8f08fa7ae 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -853,7 +853,7 @@ void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) } EXPORT_SYMBOL_GPL(ip_tunnel_dellink); -int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, +int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, struct rtnl_link_ops *ops, char *devname) { struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); @@ -899,7 +899,7 @@ static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head) unregister_netdevice_queue(itn->fb_tunnel_dev, head); } -void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn) +void ip_tunnel_delete_net(struct ip_tunnel_net *itn) { LIST_HEAD(list); -- cgit v1.2.3 From 300b962e5244a1ea010df7e88595faa0085b461d Mon Sep 17 00:00:00 2001 From: Anderson Lizardo Date: Sun, 2 Jun 2013 16:30:40 -0400 Subject: Bluetooth: Fix crash in l2cap_build_cmd() with small MTU If a too small MTU value is set with ioctl(HCISETACLMTU) or by a bogus controller, memory corruption happens due to a memcpy() call with negative length. Fix this crash on either incoming or outgoing connections with a MTU smaller than L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE: [ 46.885433] BUG: unable to handle kernel paging request at f56ad000 [ 46.888037] IP: [] memcpy+0x1d/0x40 [ 46.888037] *pdpt = 0000000000ac3001 *pde = 00000000373f8067 *pte = 80000000356ad060 [ 46.888037] Oops: 0002 [#1] SMP DEBUG_PAGEALLOC [ 46.888037] Modules linked in: hci_vhci bluetooth virtio_balloon i2c_piix4 uhci_hcd usbcore usb_common [ 46.888037] CPU: 0 PID: 1044 Comm: kworker/u3:0 Not tainted 3.10.0-rc1+ #12 [ 46.888037] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [ 46.888037] Workqueue: hci0 hci_rx_work [bluetooth] [ 46.888037] task: f59b15b0 ti: f55c4000 task.ti: f55c4000 [ 46.888037] EIP: 0060:[] EFLAGS: 00010212 CPU: 0 [ 46.888037] EIP is at memcpy+0x1d/0x40 [ 46.888037] EAX: f56ac1c0 EBX: fffffff8 ECX: 3ffffc6e EDX: f55c5cf2 [ 46.888037] ESI: f55c6b32 EDI: f56ad000 EBP: f55c5c68 ESP: f55c5c5c [ 46.888037] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 46.888037] CR0: 8005003b CR2: f56ad000 CR3: 3557d000 CR4: 000006f0 [ 46.888037] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 46.888037] DR6: ffff0ff0 DR7: 00000400 [ 46.888037] Stack: [ 46.888037] fffffff8 00000010 00000003 f55c5cac f8c6a54c ffffffff f8c69eb2 00000000 [ 46.888037] f4783cdc f57f0070 f759c590 1001c580 00000003 0200000a 00000000 f5a88560 [ 46.888037] f5ba2600 f5a88560 00000041 00000000 f55c5d90 f8c6f4c7 00000008 f55c5cf2 [ 46.888037] Call Trace: [ 46.888037] [] l2cap_send_cmd+0x1cc/0x230 [bluetooth] [ 46.888037] [] ? l2cap_global_chan_by_psm+0x152/0x1a0 [bluetooth] [ 46.888037] [] l2cap_connect+0x3f7/0x540 [bluetooth] [ 46.888037] [] ? trace_hardirqs_off+0xb/0x10 [ 46.888037] [] ? mark_held_locks+0x68/0x110 [ 46.888037] [] ? mutex_lock_nested+0x280/0x360 [ 46.888037] [] ? __mutex_unlock_slowpath+0xa9/0x150 [ 46.888037] [] ? trace_hardirqs_on_caller+0xec/0x1b0 [ 46.888037] [] ? mutex_lock_nested+0x268/0x360 [ 46.888037] [] ? trace_hardirqs_on+0xb/0x10 [ 46.888037] [] l2cap_recv_frame+0xb2d/0x1d30 [bluetooth] [ 46.888037] [] ? mark_held_locks+0x68/0x110 [ 46.888037] [] ? __mutex_unlock_slowpath+0xa9/0x150 [ 46.888037] [] ? trace_hardirqs_on_caller+0xec/0x1b0 [ 46.888037] [] l2cap_recv_acldata+0x2a1/0x320 [bluetooth] [ 46.888037] [] hci_rx_work+0x518/0x810 [bluetooth] [ 46.888037] [] ? hci_rx_work+0x132/0x810 [bluetooth] [ 46.888037] [] process_one_work+0x1a9/0x600 [ 46.888037] [] ? process_one_work+0x12b/0x600 [ 46.888037] [] ? worker_thread+0x19e/0x320 [ 46.888037] [] ? worker_thread+0x19e/0x320 [ 46.888037] [] worker_thread+0xf7/0x320 [ 46.888037] [] ? rescuer_thread+0x290/0x290 [ 46.888037] [] kthread+0xa8/0xb0 [ 46.888037] [] ret_from_kernel_thread+0x1b/0x28 [ 46.888037] [] ? flush_kthread_worker+0x120/0x120 [ 46.888037] Code: c3 90 8d 74 26 00 e8 63 fc ff ff eb e8 90 55 89 e5 83 ec 0c 89 5d f4 89 75 f8 89 7d fc 3e 8d 74 26 00 89 cb 89 c7 c1 e9 02 89 d6 a5 89 d9 83 e1 03 74 02 f3 a4 8b 5d f4 8b 75 f8 8b 7d fc 89 [ 46.888037] EIP: [] memcpy+0x1d/0x40 SS:ESP 0068:f55c5c5c [ 46.888037] CR2: 00000000f56ad000 [ 46.888037] ---[ end trace 0217c1f4d78714a9 ]--- Signed-off-by: Anderson Lizardo Cc: stable@vger.kernel.org Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- net/bluetooth/l2cap_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 24bee07ee4ce..4be6a264b475 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2852,6 +2852,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", conn, code, ident, dlen); + if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) + return NULL; + len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; count = min_t(unsigned int, conn->mtu, len); -- cgit v1.2.3 From 59f45d576a0715026d1919ab8a12047616204656 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 13 Jun 2013 11:01:13 +0300 Subject: Bluetooth: Fix conditions for HCI_Delete_Stored_Link_Key Even though the HCI_Delete_Stored_Link_Key command is mandatory for 1.1 and later controllers some controllers do not seem to support it properly as was witnessed by one Broadcom based controller: < HCI Command: Delete Stored Link Key (0x03|0x0012) plen 7 bdaddr 00:00:00:00:00:00 all 1 > HCI Event: Command Complete (0x0e) plen 4 Delete Stored Link Key (0x03|0x0012) ncmd 1 status 0x11 deleted 0 Error: Unsupported Feature or Parameter Value Luckily this same controller also doesn't list the command in its supported commands bit mask (counting from 0 bit 7 of octet 6): < HCI Command: Read Local Supported Commands (0x04|0x0002) plen 0 > HCI Event: Command Complete (0x0e) plen 68 Read Local Supported Commands (0x04|0x0002) ncmd 1 status 0x00 Commands: ffffffffffff1ffffffffffff30fffff3f Therefore, it makes sense to move sending of HCI_Delete_Stored_Link_Key to after receiving the supported commands response and to only send it if its respective bit in the mask is set. The downside of this is that we no longer send the HCI_Delete_Stored_Link_Key command for Bluetooth 1.1 controllers since HCI_Read_Local_Supported_Command was introduced in version 1.2, but this is an acceptable penalty as the command in question shouldn't affect critical behavior. Reported-by: Pavel Machek Signed-off-by: Johan Hedberg Tested-by: Pavel Machek Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- net/bluetooth/hci_core.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d817c932d634..ace5e55fe5a3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -341,7 +341,6 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) static void bredr_setup(struct hci_request *req) { - struct hci_cp_delete_stored_link_key cp; __le16 param; __u8 flt_type; @@ -365,10 +364,6 @@ static void bredr_setup(struct hci_request *req) param = __constant_cpu_to_le16(0x7d00); hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); - bacpy(&cp.bdaddr, BDADDR_ANY); - cp.delete_all = 0x01; - hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); - /* Read page scan parameters */ if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); @@ -602,6 +597,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) struct hci_dev *hdev = req->hdev; u8 p; + /* Only send HCI_Delete_Stored_Link_Key if it is supported */ + if (hdev->commands[6] & 0x80) { + struct hci_cp_delete_stored_link_key cp; + + bacpy(&cp.bdaddr, BDADDR_ANY); + cp.delete_all = 0x01; + hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, + sizeof(cp), &cp); + } + if (hdev->commands[5] & 0x10) hci_setup_link_policy(req); -- cgit v1.2.3 From c5c7774d7eb4397891edca9ebdf750ba90977a69 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 12 Jun 2013 14:26:44 -0400 Subject: sctp: fully initialize sctp_outq in sctp_outq_init In commit 2f94aabd9f6c925d77aecb3ff020f1cc12ed8f86 (refactor sctp_outq_teardown to insure proper re-initalization) we modified sctp_outq_teardown to use sctp_outq_init to fully re-initalize the outq structure. Steve West recently asked me why I removed the q->error = 0 initalization from sctp_outq_teardown. I did so because I was operating under the impression that sctp_outq_init would properly initalize that value for us, but it doesn't. sctp_outq_init operates under the assumption that the outq struct is all 0's (as it is when called from sctp_association_init), but using it in __sctp_outq_teardown violates that assumption. We should do a memset in sctp_outq_init to ensure that the entire structure is in a known state there instead. Signed-off-by: Neil Horman Reported-by: "West, Steve (NSN - US/Fort Worth)" CC: Vlad Yasevich CC: netdev@vger.kernel.org CC: davem@davemloft.net Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 32a4625fef77..be35e2dbcc9a 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -206,6 +206,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary, */ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) { + memset(q, 0, sizeof(struct sctp_outq)); + q->asoc = asoc; INIT_LIST_HEAD(&q->out_chunk_list); INIT_LIST_HEAD(&q->control_chunk_list); @@ -213,11 +215,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) INIT_LIST_HEAD(&q->sacked); INIT_LIST_HEAD(&q->abandoned); - q->fast_rtx = 0; - q->outstanding_bytes = 0; q->empty = 1; - q->cork = 0; - q->out_qlen = 0; } /* Free the outqueue structure and any related pending chunks. -- cgit v1.2.3 From 788dfcacacfbdd51f9c92065bd8e136686f07a29 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Mon, 17 Jun 2013 11:28:03 +0900 Subject: vlan: restore ethtool ABI to control VLAN hardware acceleration As part of the push to add 802.1ad server provider tagging support to the kernel the VLAN features flags were renamed. Unfortunately the kernel name for the VLAN hardware acceleration features that the kernel shows user space was included in the rename, which broke ethtool (txvlan and rxvlan options do not work). This patch restores the original names, i.e. the original ABI. If we wanted to make clear to users that we are refering to CTAGs we can always change ethtool's short_name and long_name for these features (for example something along the lines of txvlan -> txvlan-ctag, tx-vlan-offload -> tx-vlan-ctag-offload). Cc: Patrick McHardy Cc: David S. Miller Cc: netdev@vger.kernel.org Signed-off-by: Fernando Luis Vazquez Cao Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/ethtool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 22efdaa76ebf..ce91766eeca9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -60,10 +60,10 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6", [NETIF_F_HIGHDMA_BIT] = "highdma", [NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist", - [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-ctag-hw-insert", + [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert", - [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-ctag-hw-parse", - [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-ctag-filter", + [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse", + [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter", [NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert", [NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse", [NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter", -- cgit v1.2.3 From 32de868cbc6bee010d2cee95b5071b25ecbec8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Sun, 16 Jun 2013 23:20:34 +0200 Subject: bridge: fix switched interval for MLD Query types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit General Queries (the one with the Multicast Address field set to zero / '::') are supposed to have a Maximum Response Delay of [Query Response Interval], while for Multicast-Address-Specific Queries it is [Last Listener Query Interval] - not the other way round. (see RFC2710, section 7.3+7.8) Signed-off-by: Linus Lüssing Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 81f2389f78eb..d6448e35e027 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -465,8 +465,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, skb_set_transport_header(skb, skb->len); mldq = (struct mld_msg *) icmp6_hdr(skb); - interval = ipv6_addr_any(group) ? br->multicast_last_member_interval : - br->multicast_query_response_interval; + interval = ipv6_addr_any(group) ? + br->multicast_query_response_interval : + br->multicast_last_member_interval; mldq->mld_type = ICMPV6_MGM_QUERY; mldq->mld_code = 0; -- cgit v1.2.3 From 33be081a812098567898bbe23b581460331a986f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 31 May 2013 03:27:55 +0200 Subject: ipv6: ndisc: fix ndisc_send_redirect writing to the wrong skb Since some refactoring in 5f5a011, ndisc_send_redirect called ndisc_fill_redirect_hdr_option on the wrong skb, leading to data corruption or in the worst case a panic when the skb_put failed. Signed-off-by: Matthias Schiffer Reviewed-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2712ab22a174..ca4ffcc287f1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1493,7 +1493,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) */ if (ha) - ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, ha); + ndisc_fill_addr_option(buff, ND_OPT_TARGET_LL_ADDR, ha); /* * build redirect option and copy skb over to the new packet. -- cgit v1.2.3 From 3a5a423bb958ad22eeccca66c533e85bf69ba10e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jun 2013 10:09:57 +0200 Subject: nl80211: fix attrbuf access race by allocating a separate one Since my commit 3713b4e364 ("nl80211: allow splitting wiphy information in dumps"), nl80211_dump_wiphy() uses the global nl80211_fam.attrbuf for parsing the incoming data. This wouldn't be a problem if it only did so on the first dump iteration which is locked against other commands in generic netlink, but due to space constraints in cb->args (the needed state doesn't fit) I decided to always parse the original message. That's racy though since nl80211_fam.attrbuf could be used by some other parsing in generic netlink concurrently. For now, fix this by allocating a separate parse buffer (it's a bit too big for the stack, currently 1448 bytes on 64-bit). For -next, I'll change the code to parse into the global buffer in the first round only and then allocate a smaller buffer to keep the data in cb->args. Reported-by: Linus Torvalds Acked-by: David S. Miller Acked-by: John W. Linville Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d5aed3bb3945..b14b7e3cb6e6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1564,12 +1564,17 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) struct cfg80211_registered_device *dev; s64 filter_wiphy = -1; bool split = false; - struct nlattr **tb = nl80211_fam.attrbuf; + struct nlattr **tb; int res; + /* will be zeroed in nlmsg_parse() */ + tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL); + if (!tb) + return -ENOMEM; + mutex_lock(&cfg80211_mutex); res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, - tb, nl80211_fam.maxattr, nl80211_policy); + tb, NL80211_ATTR_MAX, nl80211_policy); if (res == 0) { split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; if (tb[NL80211_ATTR_WIPHY]) @@ -1583,6 +1588,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) netdev = dev_get_by_index(sock_net(skb->sk), ifidx); if (!netdev) { mutex_unlock(&cfg80211_mutex); + kfree(tb); return -ENODEV; } if (netdev->ieee80211_ptr) { @@ -1593,6 +1599,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) dev_put(netdev); } } + kfree(tb); list_for_each_entry(dev, &cfg80211_rdev_list, list) { if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) -- cgit v1.2.3