From 7360fe16c5e4eee3fd629614e95e44e1b0431d8d Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 10 Sep 2020 21:32:55 -0700 Subject: [PATCH 1/3] core: Update IID every time netdevice is brought down This is done to randomize the IPv6 address generation. This also assigns a different IID to every rmnet interface. CRs-Fixed: 2771389 Change-Id: I427481f1eeda098a2ebbd0c8ce88030eb0cd6cfd Signed-off-by: Subash Abhinov Kasiviswanathan --- core/rmnet_config.c | 4 +++- core/rmnet_vnd.c | 10 +++++++++- core/rmnet_vnd.h | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/core/rmnet_config.c b/core/rmnet_config.c index 1d0d71dd0d99..4448a8efaf3b 100644 --- a/core/rmnet_config.c +++ b/core/rmnet_config.c @@ -331,7 +331,9 @@ static int rmnet_config_notify_cb(struct notifier_block *nb, netdev_dbg(dev, "Kernel unregister\n"); rmnet_force_unassociate_device(dev); break; - + case NETDEV_DOWN: + rmnet_vnd_reset_mac_addr(dev); + break; default: break; } diff --git a/core/rmnet_vnd.c b/core/rmnet_vnd.c index 3674b3f94ef6..d5187be0497d 100644 --- a/core/rmnet_vnd.c +++ b/core/rmnet_vnd.c @@ -357,7 +357,7 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev) rmnet_dev->netdev_ops = &rmnet_vnd_ops; rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE; rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM; - random_ether_addr(rmnet_dev->dev_addr); + random_ether_addr(rmnet_dev->perm_addr); rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN; /* Raw IP mode */ @@ -444,3 +444,11 @@ int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) return 0; } + +void rmnet_vnd_reset_mac_addr(struct net_device *dev) +{ + if (dev->netdev_ops != &rmnet_vnd_ops) + return; + + random_ether_addr(dev->perm_addr); +} diff --git a/core/rmnet_vnd.h b/core/rmnet_vnd.h index 8b26f7cb63f9..7fa9500a2aca 100644 --- a/core/rmnet_vnd.h +++ b/core/rmnet_vnd.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,4 +27,5 @@ void rmnet_vnd_rx_fixup(struct net_device *dev, u32 skb_len); void rmnet_vnd_tx_fixup(struct net_device *dev, u32 skb_len); u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev); void rmnet_vnd_setup(struct net_device *dev); +void rmnet_vnd_reset_mac_addr(struct net_device *dev); #endif /* _RMNET_VND_H_ */ From 4ede88477be4dda2e8a9b8b35b0453b0ecd82b14 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Mon, 14 Sep 2020 17:12:50 -0600 Subject: [PATCH 2/3] rmnet_core: Check for contiguous QMAP headers during deaggregation After the introduction of scatter gather support, it's possible that the QMAP headers may be split across pages. This patch adds proper handling for the headers during deaggregation from the original SKB from the physical device when building the descriptors used elsewhere in the rmnet driver. Change-Id: If62cf8b4993fe01b6f43e9f16f08c134d18437b8 Signed-off-by: Sean Tranchetti --- core/rmnet_descriptor.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/core/rmnet_descriptor.c b/core/rmnet_descriptor.c index c0b95f330c4c..79612ec49cd3 100644 --- a/core/rmnet_descriptor.c +++ b/core/rmnet_descriptor.c @@ -558,20 +558,36 @@ int rmnet_frag_flow_command(struct rmnet_frag_descriptor *frag_desc, } EXPORT_SYMBOL(rmnet_frag_flow_command); -static int rmnet_frag_deaggregate_one(struct skb_shared_info *shinfo, +static int rmnet_frag_deaggregate_one(struct sk_buff *skb, struct rmnet_port *port, struct list_head *list, u32 start_frag) { + struct skb_shared_info *shinfo = skb_shinfo(skb); struct rmnet_frag_descriptor *frag_desc; - struct rmnet_map_header *maph; + struct rmnet_map_header *maph, __maph; skb_frag_t *frag; u32 i; u32 pkt_len; int rc; frag = &shinfo->frags[start_frag]; - maph = skb_frag_address(frag); + /* Grab the QMAP header. Careful, as there's no guarantee that it's + * continugous! + */ + if (likely(skb_frag_size(frag) >= sizeof(*maph))) { + maph = skb_frag_address(frag); + } else { + /* The header's split across pages. We can rebuild it. + * Probably not faster or stronger than before. But certainly + * more linear. + */ + if (skb_copy_bits(skb, 0, &__maph, sizeof(&__maph)) < 0) + return -1; + + maph = &__maph; + } + pkt_len = ntohs(maph->pkt_len); /* Catch empty frames */ if (!pkt_len) @@ -590,9 +606,19 @@ static int rmnet_frag_deaggregate_one(struct skb_shared_info *shinfo, u32 hsize = 0; u8 type; - type = ((struct rmnet_map_v5_coal_header *) - (maph + 1))->header_type; - switch (type) { + /* Check the type. This seems like should be overkill for less + * than a single byte, doesn't it? + */ + if (likely(skb_frag_size(frag) >= sizeof(*maph) + 1)) { + type = *((u8 *)maph + sizeof(*maph)); + } else { + if (skb_copy_bits(skb, sizeof(*maph), &type, + sizeof(type)) < 0) + return -1; + } + + /* Type only uses the first 7 bits */ + switch ((type & 0xFE) >> 1) { case RMNET_MAP_HEADER_TYPE_COALESCING: hsize = sizeof(struct rmnet_map_v5_coal_header); break; @@ -647,7 +673,7 @@ void rmnet_frag_deaggregate(struct sk_buff *skb, struct rmnet_port *port, int rc; while (i < shinfo->nr_frags) { - rc = rmnet_frag_deaggregate_one(shinfo, port, list, i); + rc = rmnet_frag_deaggregate_one(skb, port, list, i); if (rc < 0) return; From 1b7901268f1350a6558c2b16e6e1644500b79513 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Mon, 21 Sep 2020 13:19:07 -0600 Subject: [PATCH 3/3] rmnet_core: Pass correct size to skb_copy_bits When copying the QMAP header during deaggregation, the size of the data to copy was incorrectly passed to skb_copy_bits() as the size of the pointer instead of the struct. This lead to copying more data onto the stack than there was room for. Change-Id: I19208a8df2d8ce25a22fff95b71f1c56dcddec89 Signed-off-by: Sean Tranchetti --- core/rmnet_descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rmnet_descriptor.c b/core/rmnet_descriptor.c index 79612ec49cd3..c71d44c63d2e 100644 --- a/core/rmnet_descriptor.c +++ b/core/rmnet_descriptor.c @@ -582,7 +582,7 @@ static int rmnet_frag_deaggregate_one(struct sk_buff *skb, * Probably not faster or stronger than before. But certainly * more linear. */ - if (skb_copy_bits(skb, 0, &__maph, sizeof(&__maph)) < 0) + if (skb_copy_bits(skb, 0, &__maph, sizeof(__maph)) < 0) return -1; maph = &__maph;