| From foo@baz Sun Nov 22 12:00:04 PM CET 2020 |
| From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> |
| Date: Fri, 13 Nov 2020 13:12:05 -0700 |
| Subject: net: qualcomm: rmnet: Fix incorrect receive packet handling during cleanup |
| |
| From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> |
| |
| [ Upstream commit fc70f5bf5e525dde81565f0a30d5e39168062eba ] |
| |
| During rmnet unregistration, the real device rx_handler is first cleared |
| followed by the removal of rx_handler_data after the rcu synchronization. |
| |
| Any packets in the receive path may observe that the rx_handler is NULL. |
| However, there is no check when dereferencing this value to use the |
| rmnet_port information. |
| |
| This fixes following splat by adding the NULL check. |
| |
| Unable to handle kernel NULL pointer dereference at virtual |
| address 000000000000000d |
| pc : rmnet_rx_handler+0x124/0x284 |
| lr : rmnet_rx_handler+0x124/0x284 |
| rmnet_rx_handler+0x124/0x284 |
| __netif_receive_skb_core+0x758/0xd74 |
| __netif_receive_skb+0x50/0x17c |
| process_backlog+0x15c/0x1b8 |
| napi_poll+0x88/0x284 |
| net_rx_action+0xbc/0x23c |
| __do_softirq+0x20c/0x48c |
| |
| Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation") |
| Signed-off-by: Sean Tranchetti <stranche@codeaurora.org> |
| Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> |
| Link: https://lore.kernel.org/r/1605298325-3705-1-git-send-email-subashab@codeaurora.org |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 5 +++++ |
| 1 file changed, 5 insertions(+) |
| |
| --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c |
| +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c |
| @@ -197,6 +197,11 @@ rx_handler_result_t rmnet_rx_handler(str |
| |
| dev = skb->dev; |
| port = rmnet_get_port_rcu(dev); |
| + if (unlikely(!port)) { |
| + atomic_long_inc(&skb->dev->rx_nohandler); |
| + kfree_skb(skb); |
| + goto done; |
| + } |
| |
| switch (port->rmnet_mode) { |
| case RMNET_EPMODE_VND: |