rmnet_core: fix race condition in rmnet_get_packets
In rmnet powersave work, rmnet_get_packets() could access NULL dev pointer if rmnet_dellink() is nullifying the dev pointer at the same time. 18377 [ 72.651710][ T1527] Unable to handle kernel NULL pointer dereference at virtual address 00000000000009d0 18424 [ 72.653999][ T1527] Call trace: 18425 [ 72.654085][ T1527] rmnet_get_packets+0xc4/0x11c [rmnet_core] 18426 [ 72.654170][ T1527] qmi_rmnet_check_stats_2+0x80/0x410 [rmnet_core] 18427 [ 72.654180][ T1527] process_one_work+0x260/0x804 This change Uses the rcu variant of the hlist traversal function in rmnet_get_packet for safe concurrency with the hlist del primitives. It also checks dev pointer before accessing the dev private structure. The existing synchronize rcu call in rmnet_dellink ensures that the ep and dev structure are not freed while being referenced in rcu read session of rmnet_get_packets. Change-Id: Ib5f5aff6e76f9fffd9110a2aa924ad6ab090991f Signed-off-by: Weiyi Chen <quic_weiyic@quicinc.com>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
48a12a6f04
commit
a2ea279ba9
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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
|
||||
@@ -670,6 +671,7 @@ EXPORT_SYMBOL(rmnet_init_qmi_pt);
|
||||
|
||||
void rmnet_get_packets(void *port, u64 *rx, u64 *tx)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct rmnet_priv *priv;
|
||||
struct rmnet_pcpu_stats *ps;
|
||||
unsigned int cpu, start;
|
||||
@@ -683,8 +685,12 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx)
|
||||
*tx = 0;
|
||||
*rx = 0;
|
||||
rcu_read_lock();
|
||||
hash_for_each(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) {
|
||||
priv = netdev_priv(ep->egress_dev);
|
||||
hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep, bkt, ep,
|
||||
hlnode) {
|
||||
dev = ep->egress_dev;
|
||||
if (!dev)
|
||||
continue;
|
||||
priv = netdev_priv(dev);
|
||||
for_each_possible_cpu(cpu) {
|
||||
ps = per_cpu_ptr(priv->pcpu_stats, cpu);
|
||||
do {
|
||||
|
Reference in New Issue
Block a user