From 21e13df826ed6569d15bea86fe8ee9815eb03844 Mon Sep 17 00:00:00 2001 From: Weiyi Chen Date: Tue, 7 Dec 2021 13:22:14 -0800 Subject: [PATCH] dfc: fix use-after-free When IPA failed to send a QMAP packet, the skb is freed in IPA so accessing the skb after IPA failure will result in use-after-free. Remove the skb access after IPA send failure. Change-Id: Id12894a8f4cc3d7bec717413d48f2430e1c959cf Signed-off-by: Weiyi Chen --- core/dfc_qmap.c | 9 ++++++--- core/rmnet_ctl_client.c | 9 +++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/core/dfc_qmap.c b/core/dfc_qmap.c index f371a0f6e7bf..6afc12cdb15f 100644 --- a/core/dfc_qmap.c +++ b/core/dfc_qmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -139,11 +140,13 @@ static void dfc_qmap_send_cmd(struct sk_buff *skb) { trace_dfc_qmap(skb->data, skb->len, false); - if (unlikely(!rmnet_ctl || !rmnet_ctl->send) || - rmnet_ctl->send(rmnet_ctl_handle, skb)) { - pr_err("Failed to send to rmnet ctl\n"); + if (unlikely(!rmnet_ctl || !rmnet_ctl->send)) { kfree_skb(skb); + return; } + + if (rmnet_ctl->send(rmnet_ctl_handle, skb)) + pr_err("Failed to send to rmnet ctl\n"); } static void dfc_qmap_send_inband_ack(struct dfc_qmi_data *dfc, diff --git a/core/rmnet_ctl_client.c b/core/rmnet_ctl_client.c index 4958deac1c75..1ec53dea3f18 100644 --- a/core/rmnet_ctl_client.c +++ b/core/rmnet_ctl_client.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * RMNET_CTL client handlers * @@ -171,8 +172,10 @@ int rmnet_ctl_send_client(void *handle, struct sk_buff *skb) struct rmnet_ctl_dev *dev; int rc = -EINVAL; - if (client != rcu_dereference(ctl_ep.client)) + if (client != rcu_dereference(ctl_ep.client)) { + kfree_skb(skb); return rc; + } rmnet_ctl_log_info("TX", skb->data, skb->len); @@ -181,11 +184,13 @@ int rmnet_ctl_send_client(void *handle, struct sk_buff *skb) dev = rcu_dereference(ctl_ep.dev); if (dev && dev->xmit) rc = dev->xmit(dev, skb); + else + kfree_skb(skb); rcu_read_unlock(); if (rc) - rmnet_ctl_log_err("TXE", rc, skb->data, skb->len); + rmnet_ctl_log_err("TXE", rc, NULL, 0); return rc; }