* [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled
@ 2018-02-16 22:56 Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 1/3] net: qualcomm: rmnet: Fix crash on real dev unregistration Subash Abhinov Kasiviswanathan
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Subash Abhinov Kasiviswanathan @ 2018-02-16 22:56 UTC (permalink / raw)
To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
Patch 1 and 2 fixes issues identified when CONFIG_DEBUG_PREEMPT was
enabled. These involve APIs which were called in invalid contexts.
Patch 3 is a null derefence fix identified by code inspection.
Subash Abhinov Kasiviswanathan (3):
net: qualcomm: rmnet: Fix crash on real dev unregistration
net: qualcomm: rmnet: Fix warning seen with 64 bit stats
net: qualcomm: rmnet: Fix possible null dereference in command
processing
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 68 +++++-----------------
.../ethernet/qualcomm/rmnet/rmnet_map_command.c | 5 ++
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 2 +-
3 files changed, 20 insertions(+), 55 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net 1/3] net: qualcomm: rmnet: Fix crash on real dev unregistration
2018-02-16 22:56 [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled Subash Abhinov Kasiviswanathan
@ 2018-02-16 22:56 ` Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 2/3] net: qualcomm: rmnet: Fix warning seen with 64 bit stats Subash Abhinov Kasiviswanathan
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Subash Abhinov Kasiviswanathan @ 2018-02-16 22:56 UTC (permalink / raw)
To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
With CONFIG_DEBUG_PREEMPT enabled, a crash with the following call
stack was observed when removing a real dev which had rmnet devices
attached to it.
To fix this, remove the netdev_upper link APIs and instead use the
existing information in rmnet_port and rmnet_priv to get the
association between real and rmnet devs.
BUG: sleeping function called from invalid context
in_atomic(): 0, irqs_disabled(): 0, pid: 5762, name: ip
Preemption disabled at:
[<ffffff9d49043564>] debug_object_active_state+0xa4/0x16c
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
Modules linked in:
PC is at ___might_sleep+0x13c/0x180
LR is at ___might_sleep+0x17c/0x180
[<ffffff9d48ce0924>] ___might_sleep+0x13c/0x180
[<ffffff9d48ce09c0>] __might_sleep+0x58/0x8c
[<ffffff9d49d6253c>] mutex_lock+0x2c/0x48
[<ffffff9d48ed4840>] kernfs_remove_by_name_ns+0x48/0xa8
[<ffffff9d48ed6ec8>] sysfs_remove_link+0x30/0x58
[<ffffff9d49b05840>] __netdev_adjacent_dev_remove+0x14c/0x1e0
[<ffffff9d49b05914>] __netdev_adjacent_dev_unlink_lists+0x40/0x68
[<ffffff9d49b08820>] netdev_upper_dev_unlink+0xb4/0x1fc
[<ffffff9d494a29f0>] rmnet_dev_walk_unreg+0x6c/0xc8
[<ffffff9d49b00b40>] netdev_walk_all_lower_dev_rcu+0x58/0xb4
[<ffffff9d494a30fc>] rmnet_config_notify_cb+0xf4/0x134
[<ffffff9d48cd21b4>] raw_notifier_call_chain+0x58/0x78
[<ffffff9d49b028a4>] call_netdevice_notifiers_info+0x48/0x78
[<ffffff9d49b0b568>] rollback_registered_many+0x230/0x3c8
[<ffffff9d49b0b738>] unregister_netdevice_many+0x38/0x94
[<ffffff9d49b1e110>] rtnl_delete_link+0x58/0x88
[<ffffff9d49b201dc>] rtnl_dellink+0xbc/0x1cc
[<ffffff9d49b2355c>] rtnetlink_rcv_msg+0xb0/0x244
[<ffffff9d49b5230c>] netlink_rcv_skb+0xb4/0xdc
[<ffffff9d49b204f4>] rtnetlink_rcv+0x34/0x44
[<ffffff9d49b51af0>] netlink_unicast+0x1ec/0x294
[<ffffff9d49b51fdc>] netlink_sendmsg+0x320/0x390
[<ffffff9d49ae6858>] sock_sendmsg+0x54/0x60
[<ffffff9d49ae6f94>] ___sys_sendmsg+0x298/0x2b0
[<ffffff9d49ae98f8>] SyS_sendmsg+0xb4/0xf0
[<ffffff9d48c83770>] el0_svc_naked+0x24/0x28
Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation")
Fixes: 60d58f971c10 ("net: qualcomm: rmnet: Implement bridge mode")
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 68 +++++-----------------
1 file changed, 14 insertions(+), 54 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
index 7e7704d..c494918 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -43,12 +43,6 @@
/* Local Definitions and Declarations */
-struct rmnet_walk_data {
- struct net_device *real_dev;
- struct list_head *head;
- struct rmnet_port *port;
-};
-
static int rmnet_is_real_dev_registered(const struct net_device *real_dev)
{
return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler;
@@ -112,17 +106,14 @@ static int rmnet_register_real_device(struct net_device *real_dev)
static void rmnet_unregister_bridge(struct net_device *dev,
struct rmnet_port *port)
{
- struct net_device *rmnet_dev, *bridge_dev;
struct rmnet_port *bridge_port;
+ struct net_device *bridge_dev;
if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
return;
/* bridge slave handling */
if (!port->nr_rmnet_devs) {
- rmnet_dev = netdev_master_upper_dev_get_rcu(dev);
- netdev_upper_dev_unlink(dev, rmnet_dev);
-
bridge_dev = port->bridge_ep;
bridge_port = rmnet_get_port_rtnl(bridge_dev);
@@ -132,9 +123,6 @@ static void rmnet_unregister_bridge(struct net_device *dev,
bridge_dev = port->bridge_ep;
bridge_port = rmnet_get_port_rtnl(bridge_dev);
- rmnet_dev = netdev_master_upper_dev_get_rcu(bridge_dev);
- netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
-
rmnet_unregister_real_device(bridge_dev, bridge_port);
}
}
@@ -173,10 +161,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
if (err)
goto err1;
- err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL, extack);
- if (err)
- goto err2;
-
port->rmnet_mode = mode;
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
@@ -193,8 +177,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
return 0;
-err2:
- rmnet_vnd_dellink(mux_id, port, ep);
err1:
rmnet_unregister_real_device(real_dev, port);
err0:
@@ -204,14 +186,13 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
static void rmnet_dellink(struct net_device *dev, struct list_head *head)
{
+ struct rmnet_priv *priv = netdev_priv(dev);
struct net_device *real_dev;
struct rmnet_endpoint *ep;
struct rmnet_port *port;
u8 mux_id;
- rcu_read_lock();
- real_dev = netdev_master_upper_dev_get_rcu(dev);
- rcu_read_unlock();
+ real_dev = priv->real_dev;
if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
return;
@@ -219,7 +200,6 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
port = rmnet_get_port_rtnl(real_dev);
mux_id = rmnet_vnd_get_mux(dev);
- netdev_upper_dev_unlink(dev, real_dev);
ep = rmnet_get_endpoint(port, mux_id);
if (ep) {
@@ -233,30 +213,13 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
unregister_netdevice_queue(dev, head);
}
-static int rmnet_dev_walk_unreg(struct net_device *rmnet_dev, void *data)
-{
- struct rmnet_walk_data *d = data;
- struct rmnet_endpoint *ep;
- u8 mux_id;
-
- mux_id = rmnet_vnd_get_mux(rmnet_dev);
- ep = rmnet_get_endpoint(d->port, mux_id);
- if (ep) {
- hlist_del_init_rcu(&ep->hlnode);
- rmnet_vnd_dellink(mux_id, d->port, ep);
- kfree(ep);
- }
- netdev_upper_dev_unlink(rmnet_dev, d->real_dev);
- unregister_netdevice_queue(rmnet_dev, d->head);
-
- return 0;
-}
-
static void rmnet_force_unassociate_device(struct net_device *dev)
{
struct net_device *real_dev = dev;
- struct rmnet_walk_data d;
+ struct hlist_node *tmp_ep;
+ struct rmnet_endpoint *ep;
struct rmnet_port *port;
+ unsigned long bkt_ep;
LIST_HEAD(list);
if (!rmnet_is_real_dev_registered(real_dev))
@@ -264,16 +227,19 @@ static void rmnet_force_unassociate_device(struct net_device *dev)
ASSERT_RTNL();
- d.real_dev = real_dev;
- d.head = &list;
-
port = rmnet_get_port_rtnl(dev);
- d.port = port;
rcu_read_lock();
rmnet_unregister_bridge(dev, port);
- netdev_walk_all_lower_dev_rcu(real_dev, rmnet_dev_walk_unreg, &d);
+ hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
+ unregister_netdevice_queue(ep->egress_dev, &list);
+ rmnet_vnd_dellink(ep->mux_id, port, ep);
+
+ hlist_del_init_rcu(&ep->hlnode);
+ kfree(ep);
+ }
+
rcu_read_unlock();
unregister_netdevice_many(&list);
@@ -422,11 +388,6 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
if (err)
return -EBUSY;
- err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
- extack);
- if (err)
- return -EINVAL;
-
slave_port = rmnet_get_port(slave_dev);
slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
slave_port->bridge_ep = real_dev;
@@ -449,7 +410,6 @@ int rmnet_del_bridge(struct net_device *rmnet_dev,
port->rmnet_mode = RMNET_EPMODE_VND;
port->bridge_ep = NULL;
- netdev_upper_dev_unlink(slave_dev, rmnet_dev);
slave_port = rmnet_get_port(slave_dev);
rmnet_unregister_real_device(slave_dev, slave_port);
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net 2/3] net: qualcomm: rmnet: Fix warning seen with 64 bit stats
2018-02-16 22:56 [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 1/3] net: qualcomm: rmnet: Fix crash on real dev unregistration Subash Abhinov Kasiviswanathan
@ 2018-02-16 22:56 ` Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 3/3] net: qualcomm: rmnet: Fix possible null dereference in command processing Subash Abhinov Kasiviswanathan
2018-02-19 16:18 ` [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Subash Abhinov Kasiviswanathan @ 2018-02-16 22:56 UTC (permalink / raw)
To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
With CONFIG_DEBUG_PREEMPT enabled, a warning was seen on device
creation. This occurs due to the incorrect cpu API usage in
ndo_get_stats64 handler.
BUG: using smp_processor_id() in preemptible [00000000] code: rmnetcli/5743
caller is debug_smp_processor_id+0x1c/0x24
Call trace:
[<ffffff9d48c8967c>] dump_backtrace+0x0/0x2a8
[<ffffff9d48c89bbc>] show_stack+0x20/0x28
[<ffffff9d4901fff8>] dump_stack+0xa8/0xe0
[<ffffff9d490421e0>] check_preemption_disabled+0x104/0x108
[<ffffff9d49042200>] debug_smp_processor_id+0x1c/0x24
[<ffffff9d494a36b0>] rmnet_get_stats64+0x64/0x13c
[<ffffff9d49b014e0>] dev_get_stats+0x68/0xd8
[<ffffff9d49d58df8>] rtnl_fill_stats+0x54/0x140
[<ffffff9d49b1f0b8>] rtnl_fill_ifinfo+0x428/0x9cc
[<ffffff9d49b23834>] rtmsg_ifinfo_build_skb+0x80/0xf4
[<ffffff9d49b23930>] rtnetlink_event+0x88/0xb4
[<ffffff9d48cd21b4>] raw_notifier_call_chain+0x58/0x78
[<ffffff9d49b028a4>] call_netdevice_notifiers_info+0x48/0x78
[<ffffff9d49b08bf8>] __netdev_upper_dev_link+0x290/0x5e8
[<ffffff9d49b08fcc>] netdev_master_upper_dev_link+0x3c/0x48
[<ffffff9d494a2e74>] rmnet_newlink+0xf0/0x1c8
[<ffffff9d49b23360>] rtnl_newlink+0x57c/0x6c8
[<ffffff9d49b2355c>] rtnetlink_rcv_msg+0xb0/0x244
[<ffffff9d49b5230c>] netlink_rcv_skb+0xb4/0xdc
[<ffffff9d49b204f4>] rtnetlink_rcv+0x34/0x44
[<ffffff9d49b51af0>] netlink_unicast+0x1ec/0x294
[<ffffff9d49b51fdc>] netlink_sendmsg+0x320/0x390
[<ffffff9d49ae6858>] sock_sendmsg+0x54/0x60
[<ffffff9d49ae91bc>] SyS_sendto+0x1a0/0x1e4
[<ffffff9d48c83770>] el0_svc_naked+0x24/0x28
Fixes: 192c4b5d48f2 ("net: qualcomm: rmnet: Add support for 64 bit stats")
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index 570a227..346d310 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -121,7 +121,7 @@ static void rmnet_get_stats64(struct net_device *dev,
memset(&total_stats, 0, sizeof(struct rmnet_vnd_stats));
for_each_possible_cpu(cpu) {
- pcpu_ptr = this_cpu_ptr(priv->pcpu_stats);
+ pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu);
do {
start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp);
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net 3/3] net: qualcomm: rmnet: Fix possible null dereference in command processing
2018-02-16 22:56 [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 1/3] net: qualcomm: rmnet: Fix crash on real dev unregistration Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 2/3] net: qualcomm: rmnet: Fix warning seen with 64 bit stats Subash Abhinov Kasiviswanathan
@ 2018-02-16 22:56 ` Subash Abhinov Kasiviswanathan
2018-02-19 16:18 ` [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled David Miller
3 siblings, 0 replies; 5+ messages in thread
From: Subash Abhinov Kasiviswanathan @ 2018-02-16 22:56 UTC (permalink / raw)
To: davem, netdev; +Cc: Subash Abhinov Kasiviswanathan
If a command packet with invalid mux id is received, the packet would
not have a valid endpoint. This invalid endpoint maybe dereferenced
leading to a crash. Identified by manual code inspection.
Fixes: 3352e6c45760 ("net: qualcomm: rmnet: Convert the muxed endpoint to hlist")
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
index 6bc328f..b0dbca0 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
@@ -38,6 +38,11 @@ static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
}
ep = rmnet_get_endpoint(port, mux_id);
+ if (!ep) {
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+
vnd = ep->egress_dev;
ip_family = cmd->flow_control.ip_family;
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled
2018-02-16 22:56 [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled Subash Abhinov Kasiviswanathan
` (2 preceding siblings ...)
2018-02-16 22:56 ` [PATCH net 3/3] net: qualcomm: rmnet: Fix possible null dereference in command processing Subash Abhinov Kasiviswanathan
@ 2018-02-19 16:18 ` David Miller
3 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2018-02-19 16:18 UTC (permalink / raw)
To: subashab; +Cc: netdev
From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Date: Fri, 16 Feb 2018 15:56:36 -0700
> Patch 1 and 2 fixes issues identified when CONFIG_DEBUG_PREEMPT was
> enabled. These involve APIs which were called in invalid contexts.
>
> Patch 3 is a null derefence fix identified by code inspection.
Series applied, thank you.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-02-19 16:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-16 22:56 [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 1/3] net: qualcomm: rmnet: Fix crash on real dev unregistration Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 2/3] net: qualcomm: rmnet: Fix warning seen with 64 bit stats Subash Abhinov Kasiviswanathan
2018-02-16 22:56 ` [PATCH net 3/3] net: qualcomm: rmnet: Fix possible null dereference in command processing Subash Abhinov Kasiviswanathan
2018-02-19 16:18 ` [PATCH net 0/3] net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).