From 7629d1eaf33672c9d35ba1e2ad12b459d56ca3b1 Mon Sep 17 00:00:00 2001 From: Martin Townsend Date: Tue, 19 Aug 2014 19:03:28 +0200 Subject: mac802154: fixed potential skb leak with mac802154_parse_frame_start This patch fix a memory leak if received frame was not able to parse. Signed-off-by: Martin Townsend Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/wpan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c index 3c3069fd697..4c133239ad3 100644 --- a/net/mac802154/wpan.c +++ b/net/mac802154/wpan.c @@ -573,6 +573,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) ret = mac802154_parse_frame_start(skb, &hdr); if (ret) { pr_debug("got invalid frame\n"); + kfree_skb(skb); return; } -- cgit v1.2.3-70-g09d2 From c4cb901ac667f81786b402ca7d69a9063e770b3a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Tue, 19 Aug 2014 19:03:29 +0200 Subject: ieee802154: 6lowpan_rtnl: fix correct errno value This patch correct the return value of lowpan_alloc_frag if an error occur. Errno numbers should always be negative. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/6lowpan_rtnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 016b77ee88f..71fa7d42966 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -246,7 +246,7 @@ lowpan_alloc_frag(struct sk_buff *skb, int size, return ERR_PTR(-rc); } } else { - frag = ERR_PTR(ENOMEM); + frag = ERR_PTR(-ENOMEM); } return frag; -- cgit v1.2.3-70-g09d2 From 6e361d6ffee322fcd092d97720e05032ffb98ae6 Mon Sep 17 00:00:00 2001 From: Martin Townsend Date: Tue, 19 Aug 2014 19:03:30 +0200 Subject: ieee802154: mac802154: handle the reserved dest mode by dropping the packet If received frame contains the reserved destination address mode. The frame should be dropped and free the skb. Signed-off-by: Martin Townsend Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/wpan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c index 4c133239ad3..547838822d5 100644 --- a/net/mac802154/wpan.c +++ b/net/mac802154/wpan.c @@ -462,7 +462,10 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, skb->pkt_type = PACKET_OTHERHOST; break; default: - break; + spin_unlock_bh(&sdata->mib_lock); + pr_debug("invalid dest mode\n"); + kfree_skb(skb); + return NET_RX_DROP; } spin_unlock_bh(&sdata->mib_lock); -- cgit v1.2.3-70-g09d2 From 685d632804b89ea25d3339afad162c48646ada5c Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Tue, 19 Aug 2014 19:03:31 +0200 Subject: ieee802154: 6lowpan: ensure of sending 1280 packets This patch changes the 1281 MTU to 1280. Others stack have only a 1280 byte array for uncompressed 6LoWPAN packets, this avoid that these stacks have an overflow. Sending 1281 uncompressed 6LoWPAN packets isn't also rfc complaint. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/6lowpan_rtnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 71fa7d42966..6591d27e53a 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -437,7 +437,7 @@ static void lowpan_setup(struct net_device *dev) /* Frame Control + Sequence Number + Address fields + Security Header */ dev->hard_header_len = 2 + 1 + 20 + 14; dev->needed_tailroom = 2; /* FCS */ - dev->mtu = 1281; + dev->mtu = IPV6_MIN_MTU; dev->tx_queue_len = 0; dev->flags = IFF_BROADCAST | IFF_MULTICAST; dev->watchdog_timeo = 0; -- cgit v1.2.3-70-g09d2 From 6697dabe27e03302ddfddc975275e6401defe2dd Mon Sep 17 00:00:00 2001 From: Martin Townsend Date: Tue, 19 Aug 2014 19:03:32 +0200 Subject: ieee802154: 6lowpan: ensure MTU of 1280 for 6lowpan This patch drops the userspace accessable sysfs entry for the maximum datagram size of a 6LoWPAN fragment packet. A fragment should not have a datagram size value greater than 1280 byte. Instead of make this value configurable, we accept 1280 datagram size fragment packets only. Signed-off-by: Martin Townsend Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/netns/ieee802154_6lowpan.h | 1 - net/ieee802154/reassembly.c | 15 +++------------ 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/include/net/netns/ieee802154_6lowpan.h b/include/net/netns/ieee802154_6lowpan.h index e2070960bac..8170f8d7052 100644 --- a/include/net/netns/ieee802154_6lowpan.h +++ b/include/net/netns/ieee802154_6lowpan.h @@ -16,7 +16,6 @@ struct netns_sysctl_lowpan { struct netns_ieee802154_lowpan { struct netns_sysctl_lowpan sysctl; struct netns_frags frags; - int max_dsize; }; #endif diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c index ffec6ce5100..32755cb7e64 100644 --- a/net/ieee802154/reassembly.c +++ b/net/ieee802154/reassembly.c @@ -355,8 +355,6 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) struct net *net = dev_net(skb->dev); struct lowpan_frag_info *frag_info = lowpan_cb(skb); struct ieee802154_addr source, dest; - struct netns_ieee802154_lowpan *ieee802154_lowpan = - net_ieee802154_lowpan(net); int err; source = mac_cb(skb)->source; @@ -366,8 +364,10 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) if (err < 0) goto err; - if (frag_info->d_size > ieee802154_lowpan->max_dsize) + if (frag_info->d_size > IPV6_MIN_MTU) { + net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n"); goto err; + } fq = fq_find(net, frag_info, &source, &dest); if (fq != NULL) { @@ -415,13 +415,6 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, - { - .procname = "6lowpanfrag_max_datagram_size", - .data = &init_net.ieee802154_lowpan.max_dsize, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { } }; @@ -458,7 +451,6 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net) table[1].data = &ieee802154_lowpan->frags.low_thresh; table[1].extra2 = &ieee802154_lowpan->frags.high_thresh; table[2].data = &ieee802154_lowpan->frags.timeout; - table[3].data = &ieee802154_lowpan->max_dsize; /* Don't export sysctls to unprivileged users */ if (net->user_ns != &init_user_ns) @@ -533,7 +525,6 @@ static int __net_init lowpan_frags_init_net(struct net *net) ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; - ieee802154_lowpan->max_dsize = 0xFFFF; inet_frags_init_net(&ieee802154_lowpan->frags); -- cgit v1.2.3-70-g09d2 From f161dd4122ffa73e4e12000309dca65bec80d416 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 15 Aug 2014 21:06:54 +0300 Subject: Bluetooth: Fix hci_conn reference counting for auto-connections Recently the LE passive scanning and auto-connections feature was introduced. It uses the hci_connect_le() API which returns a hci_conn along with a reference count to that object. All previous users would tie this returned reference to some existing object, such as an L2CAP channel, and there'd be no leaked references this way. For auto-connections however the reference was returned but not stored anywhere, leaving established connections with one higher reference count than they should have. Instead of playing special tricks with hci_conn_hold/drop this patch associates the returned reference from hci_connect_le() with the object that in practice does own this reference, i.e. the hci_conn_params struct that caused us to initiate a connection in the first place. Once the connection is established or fails to establish this reference is removed appropriately. One extra thing needed is to call hci_pend_le_actions_clear() before calling hci_conn_hash_flush() so that the reference is cleared before the hci_conn objects are fully removed. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_conn.c | 8 ++++++++ net/bluetooth/hci_core.c | 14 ++++++++++++-- net/bluetooth/hci_event.c | 17 +++++++++++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b5d5af3aa46..6f884e6c731 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -464,6 +464,8 @@ struct hci_conn_params { HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; + + struct hci_conn *conn; }; extern struct list_head hci_dev_list; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b50dabb3f86..faff6247ac8 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -589,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route); void hci_le_conn_failed(struct hci_conn *conn, u8 status) { struct hci_dev *hdev = conn->hdev; + struct hci_conn_params *params; + + params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst, + conn->dst_type); + if (params && params->conn) { + hci_conn_drop(params->conn); + params->conn = NULL; + } conn->state = BT_CLOSED; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c32d361c0cf..1d9c29a0056 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2536,8 +2536,13 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) { struct hci_conn_params *p; - list_for_each_entry(p, &hdev->le_conn_params, list) + list_for_each_entry(p, &hdev->le_conn_params, list) { + if (p->conn) { + hci_conn_drop(p->conn); + p->conn = NULL; + } list_del_init(&p->action); + } BT_DBG("All LE pending actions cleared"); } @@ -2578,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_dev_lock(hdev); hci_inquiry_cache_flush(hdev); - hci_conn_hash_flush(hdev); hci_pend_le_actions_clear(hdev); + hci_conn_hash_flush(hdev); hci_dev_unlock(hdev); hci_notify(hdev, HCI_DEV_DOWN); @@ -3727,6 +3732,9 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) if (!params) return; + if (params->conn) + hci_conn_drop(params->conn); + list_del(¶ms->action); list_del(¶ms->list); kfree(params); @@ -3757,6 +3765,8 @@ void hci_conn_params_clear_all(struct hci_dev *hdev) struct hci_conn_params *params, *tmp; list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { + if (params->conn) + hci_conn_drop(params->conn); list_del(¶ms->action); list_del(¶ms->list); kfree(params); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index be35598984d..a6000823f0f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4221,8 +4221,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_proto_connect_cfm(conn, ev->status); params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); - if (params) + if (params) { list_del_init(¶ms->action); + if (params->conn) { + hci_conn_drop(params->conn); + params->conn = NULL; + } + } unlock: hci_update_background_scan(hdev); @@ -4304,8 +4309,16 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); - if (!IS_ERR(conn)) + if (!IS_ERR(conn)) { + /* Store the pointer since we don't really have any + * other owner of the object besides the params that + * triggered it. This way we can abort the connection if + * the parameters get removed and keep the reference + * count consistent once the connection is established. + */ + params->conn = conn; return; + } switch (PTR_ERR(conn)) { case -EBUSY: -- cgit v1.2.3-70-g09d2