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: Ashwanth Goli <ashwanth@codeaurora.org>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
Ashwanth Goli 2017-02-24 11:03:03 -07:00 • committed by Subash Abhinov Kasiviswanathan
commit c85bfbe2e8
2 changed files with 14 additions and 6 deletions

View file

@ -1173,6 +1173,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;
@ -1228,6 +1229,16 @@ 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);
rmnet_unset_logical_endpoint_config(dev, RMNET_LOCAL_LOGICAL_ENDPOINT);

View file

@ -552,12 +552,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) ||