From d4ee8914bf11380cda657e5bb3e8b8b23e599f01 Mon Sep 17 00:00:00 2001 From: Ashwanth Goli Date: Fri, 24 Feb 2017 11:03:03 -0700 Subject: net: rmnet_data: Unset logical end points in bridge mode We clean up the logical end points only for the un-registering device in bridge mode. However, the other physical end point's local end point still points to the the un-registered device. This may lead up to a crash if one of the physical devices in bridge mode is un-registered. Fix this by unsetting the local endpoint. It is still possible that packets in a different context across cores might try to access this data. This usually manifests as packets requesting a very large headroom. Handle this by dropping these stale skb's. CRs-Fixed: 1098513 Change-Id: I1ba4d877a6ed3eca66946fe056938f0927bcd9a5 Signed-off-by: Subash Abhinov Kasiviswanathan Signed-off-by: Ashwanth Goli --- net/rmnet_data/rmnet_data_config.c | 10 ++++++++++ net/rmnet_data/rmnet_data_handlers.c | 9 +++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index fad084d03854..6fc9b86204de 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -1165,6 +1165,7 @@ static void rmnet_force_unassociate_device(struct net_device *dev) { int i, j; struct net_device *vndev; + struct rmnet_phys_ep_config *config; struct rmnet_logical_ep_conf_s *cfg; struct rmnet_free_vnd_work *vnd_work; ASSERT_RTNL(); @@ -1220,6 +1221,15 @@ static void rmnet_force_unassociate_device(struct net_device *dev) kfree(vnd_work); } + config = _rmnet_get_phys_ep_config(dev); + + if (config) { + cfg = &config->local_ep; + + if (cfg && cfg->refcount) + rmnet_unset_logical_endpoint_config + (cfg->egress_dev, RMNET_LOCAL_LOGICAL_ENDPOINT); + } /* Clear the mappings on the phys ep */ trace_rmnet_unregister_cb_clear_lepcs(dev); diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c index cef9369eace5..ae60f35b363d 100644 --- a/net/rmnet_data/rmnet_data_handlers.c +++ b/net/rmnet_data/rmnet_data_handlers.c @@ -569,12 +569,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, LOGD("headroom of %d bytes", required_headroom); if (skb_headroom(skb) < required_headroom) { - if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL)) { - LOGD("Failed to add headroom of %d bytes", - required_headroom); - kfree_skb(skb); - return 1; - } + LOGE("Not enough headroom for %d bytes", required_headroom); + kfree_skb(skb); + return 1; } if ((config->egress_data_format & RMNET_EGRESS_FORMAT_MAP_CKSUMV3) || -- cgit v1.2.3