All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code
@ 2020-12-23 21:23 Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 1/4] net-sysfs: take the rtnl lock when storing xps_cpus Antoine Tenart
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Antoine Tenart @ 2020-12-23 21:23 UTC (permalink / raw)
  To: davem, kuba, alexander.duyck; +Cc: Antoine Tenart, netdev, pabeni

Hello all,

This series fixes race conditions in the xps code, where out of bound
accesses can occur when dev->num_tc is updated, triggering oops. The
root cause is linked to locking issues. An explanation is given in each
of the commit logs.

We had a discussion on the v1 of this series about using the xps_map
mutex instead of the rtnl lock. While that seemed a better compromise,
v2 showed the added complexity wasn't best for fixes. So we decided to
go back to v1 and use the rtnl lock.

Because of this, the only differences between v1 and v3 are improvements
in the commit messages.

Thanks!
Antoine

Antoine Tenart (4):
  net-sysfs: take the rtnl lock when storing xps_cpus
  net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
  net-sysfs: take the rtnl lock when storing xps_rxqs
  net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc

 net/core/net-sysfs.c | 65 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 12 deletions(-)

-- 
2.29.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net v3 1/4] net-sysfs: take the rtnl lock when storing xps_cpus
  2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
@ 2020-12-23 21:23 ` Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 2/4] net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc Antoine Tenart
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Antoine Tenart @ 2020-12-23 21:23 UTC (permalink / raw)
  To: davem, kuba, alexander.duyck; +Cc: Antoine Tenart, netdev, pabeni

Two race conditions can be triggered when storing xps cpus, resulting in
various oops and invalid memory accesses:

1. Calling netdev_set_num_tc while netif_set_xps_queue:

   - netif_set_xps_queue uses dev->tc_num as one of the parameters to
     compute the size of new_dev_maps when allocating it. dev->tc_num is
     also used to access the map, and the compiler may generate code to
     retrieve this field multiple times in the function.

   - netdev_set_num_tc sets dev->tc_num.

   If new_dev_maps is allocated using dev->tc_num and then dev->tc_num
   is set to a higher value through netdev_set_num_tc, later accesses to
   new_dev_maps in netif_set_xps_queue could lead to accessing memory
   outside of new_dev_maps; triggering an oops.

2. Calling netif_set_xps_queue while netdev_set_num_tc is running:

   2.1. netdev_set_num_tc starts by resetting the xps queues,
        dev->tc_num isn't updated yet.

   2.2. netif_set_xps_queue is called, setting up the map with the
        *old* dev->num_tc.

   2.3. netdev_set_num_tc updates dev->tc_num.

   2.4. Later accesses to the map lead to out of bound accesses and
        oops.

   A similar issue can be found with netdev_reset_tc.

One way of triggering this is to set an iface up (for which the driver
uses netdev_set_num_tc in the open path, such as bnx2x) and writing to
xps_cpus in a concurrent thread. With the right timing an oops is
triggered.

Both issues have the same fix: netif_set_xps_queue, netdev_set_num_tc
and netdev_reset_tc should be mutually exclusive. We do that by taking
the rtnl lock in xps_cpus_store.

Fixes: 184c449f91fe ("net: Add support for XPS with QoS via traffic classes")
Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 net/core/net-sysfs.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 999b70c59761..7cc15dec1717 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1396,7 +1396,13 @@ static ssize_t xps_cpus_store(struct netdev_queue *queue,
 		return err;
 	}
 
+	if (!rtnl_trylock()) {
+		free_cpumask_var(mask);
+		return restart_syscall();
+	}
+
 	err = netif_set_xps_queue(dev, mask, index);
+	rtnl_unlock();
 
 	free_cpumask_var(mask);
 
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net v3 2/4] net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
  2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 1/4] net-sysfs: take the rtnl lock when storing xps_cpus Antoine Tenart
@ 2020-12-23 21:23 ` Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 3/4] net-sysfs: take the rtnl lock when storing xps_rxqs Antoine Tenart
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Antoine Tenart @ 2020-12-23 21:23 UTC (permalink / raw)
  To: davem, kuba, alexander.duyck; +Cc: Antoine Tenart, netdev, pabeni

Accesses to dev->xps_cpus_map (when using dev->num_tc) should be
protected by the rtnl lock, like we do for netif_set_xps_queue. I didn't
see an actual bug being triggered, but let's be safe here and take the
rtnl lock while accessing the map in sysfs.

Fixes: 184c449f91fe ("net: Add support for XPS with QoS via traffic classes")
Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 net/core/net-sysfs.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7cc15dec1717..65886bfbf822 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1317,8 +1317,8 @@ static const struct attribute_group dql_group = {
 static ssize_t xps_cpus_show(struct netdev_queue *queue,
 			     char *buf)
 {
+	int cpu, len, ret, num_tc = 1, tc = 0;
 	struct net_device *dev = queue->dev;
-	int cpu, len, num_tc = 1, tc = 0;
 	struct xps_dev_maps *dev_maps;
 	cpumask_var_t mask;
 	unsigned long index;
@@ -1328,22 +1328,31 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,
 
 	index = get_netdev_queue_index(queue);
 
+	if (!rtnl_trylock())
+		return restart_syscall();
+
 	if (dev->num_tc) {
 		/* Do not allow XPS on subordinate device directly */
 		num_tc = dev->num_tc;
-		if (num_tc < 0)
-			return -EINVAL;
+		if (num_tc < 0) {
+			ret = -EINVAL;
+			goto err_rtnl_unlock;
+		}
 
 		/* If queue belongs to subordinate dev use its map */
 		dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;
 
 		tc = netdev_txq_to_tc(dev, index);
-		if (tc < 0)
-			return -EINVAL;
+		if (tc < 0) {
+			ret = -EINVAL;
+			goto err_rtnl_unlock;
+		}
 	}
 
-	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
-		return -ENOMEM;
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto err_rtnl_unlock;
+	}
 
 	rcu_read_lock();
 	dev_maps = rcu_dereference(dev->xps_cpus_map);
@@ -1366,9 +1375,15 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,
 	}
 	rcu_read_unlock();
 
+	rtnl_unlock();
+
 	len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));
 	free_cpumask_var(mask);
 	return len < PAGE_SIZE ? len : -EINVAL;
+
+err_rtnl_unlock:
+	rtnl_unlock();
+	return ret;
 }
 
 static ssize_t xps_cpus_store(struct netdev_queue *queue,
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net v3 3/4] net-sysfs: take the rtnl lock when storing xps_rxqs
  2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 1/4] net-sysfs: take the rtnl lock when storing xps_cpus Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 2/4] net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc Antoine Tenart
@ 2020-12-23 21:23 ` Antoine Tenart
  2020-12-23 21:23 ` [PATCH net v3 4/4] net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc Antoine Tenart
  2020-12-23 23:26 ` [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Alexander Duyck
  4 siblings, 0 replies; 7+ messages in thread
From: Antoine Tenart @ 2020-12-23 21:23 UTC (permalink / raw)
  To: davem, kuba, alexander.duyck; +Cc: Antoine Tenart, netdev, pabeni

Two race conditions can be triggered when storing xps rxqs, resulting in
various oops and invalid memory accesses:

1. Calling netdev_set_num_tc while netif_set_xps_queue:

   - netif_set_xps_queue uses dev->tc_num as one of the parameters to
     compute the size of new_dev_maps when allocating it. dev->tc_num is
     also used to access the map, and the compiler may generate code to
     retrieve this field multiple times in the function.

   - netdev_set_num_tc sets dev->tc_num.

   If new_dev_maps is allocated using dev->tc_num and then dev->tc_num
   is set to a higher value through netdev_set_num_tc, later accesses to
   new_dev_maps in netif_set_xps_queue could lead to accessing memory
   outside of new_dev_maps; triggering an oops.

2. Calling netif_set_xps_queue while netdev_set_num_tc is running:

   2.1. netdev_set_num_tc starts by resetting the xps queues,
        dev->tc_num isn't updated yet.

   2.2. netif_set_xps_queue is called, setting up the map with the
        *old* dev->num_tc.

   2.3. netdev_set_num_tc updates dev->tc_num.

   2.4. Later accesses to the map lead to out of bound accesses and
        oops.

   A similar issue can be found with netdev_reset_tc.

One way of triggering this is to set an iface up (for which the driver
uses netdev_set_num_tc in the open path, such as bnx2x) and writing to
xps_rxqs in a concurrent thread. With the right timing an oops is
triggered.

Both issues have the same fix: netif_set_xps_queue, netdev_set_num_tc
and netdev_reset_tc should be mutually exclusive. We do that by taking
the rtnl lock in xps_rxqs_store.

Fixes: 8af2c06ff4b1 ("net-sysfs: Add interface for Rx queue(s) map per Tx queue")
Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 net/core/net-sysfs.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 65886bfbf822..62ca2f2c0ee6 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1499,10 +1499,17 @@ static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
 		return err;
 	}
 
+	if (!rtnl_trylock()) {
+		bitmap_free(mask);
+		return restart_syscall();
+	}
+
 	cpus_read_lock();
 	err = __netif_set_xps_queue(dev, mask, index, true);
 	cpus_read_unlock();
 
+	rtnl_unlock();
+
 	bitmap_free(mask);
 	return err ? : len;
 }
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net v3 4/4] net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
  2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
                   ` (2 preceding siblings ...)
  2020-12-23 21:23 ` [PATCH net v3 3/4] net-sysfs: take the rtnl lock when storing xps_rxqs Antoine Tenart
@ 2020-12-23 21:23 ` Antoine Tenart
  2020-12-23 23:26 ` [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Alexander Duyck
  4 siblings, 0 replies; 7+ messages in thread
From: Antoine Tenart @ 2020-12-23 21:23 UTC (permalink / raw)
  To: davem, kuba, alexander.duyck; +Cc: Antoine Tenart, netdev, pabeni

Accesses to dev->xps_rxqs_map (when using dev->num_tc) should be
protected by the rtnl lock, like we do for netif_set_xps_queue. I didn't
see an actual bug being triggered, but let's be safe here and take the
rtnl lock while accessing the map in sysfs.

Fixes: 8af2c06ff4b1 ("net-sysfs: Add interface for Rx queue(s) map per Tx queue")
Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 net/core/net-sysfs.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 62ca2f2c0ee6..daf502c13d6d 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1429,22 +1429,29 @@ static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init
 
 static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
 {
+	int j, len, ret, num_tc = 1, tc = 0;
 	struct net_device *dev = queue->dev;
 	struct xps_dev_maps *dev_maps;
 	unsigned long *mask, index;
-	int j, len, num_tc = 1, tc = 0;
 
 	index = get_netdev_queue_index(queue);
 
+	if (!rtnl_trylock())
+		return restart_syscall();
+
 	if (dev->num_tc) {
 		num_tc = dev->num_tc;
 		tc = netdev_txq_to_tc(dev, index);
-		if (tc < 0)
-			return -EINVAL;
+		if (tc < 0) {
+			ret = -EINVAL;
+			goto err_rtnl_unlock;
+		}
 	}
 	mask = bitmap_zalloc(dev->num_rx_queues, GFP_KERNEL);
-	if (!mask)
-		return -ENOMEM;
+	if (!mask) {
+		ret = -ENOMEM;
+		goto err_rtnl_unlock;
+	}
 
 	rcu_read_lock();
 	dev_maps = rcu_dereference(dev->xps_rxqs_map);
@@ -1470,10 +1477,16 @@ static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
 out_no_maps:
 	rcu_read_unlock();
 
+	rtnl_unlock();
+
 	len = bitmap_print_to_pagebuf(false, buf, mask, dev->num_rx_queues);
 	bitmap_free(mask);
 
 	return len < PAGE_SIZE ? len : -EINVAL;
+
+err_rtnl_unlock:
+	rtnl_unlock();
+	return ret;
 }
 
 static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code
  2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
                   ` (3 preceding siblings ...)
  2020-12-23 21:23 ` [PATCH net v3 4/4] net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc Antoine Tenart
@ 2020-12-23 23:26 ` Alexander Duyck
  2020-12-28 21:29   ` Jakub Kicinski
  4 siblings, 1 reply; 7+ messages in thread
From: Alexander Duyck @ 2020-12-23 23:26 UTC (permalink / raw)
  To: Antoine Tenart; +Cc: David Miller, Jakub Kicinski, Netdev, Paolo Abeni

On Wed, Dec 23, 2020 at 1:23 PM Antoine Tenart <atenart@kernel.org> wrote:
>
> Hello all,
>
> This series fixes race conditions in the xps code, where out of bound
> accesses can occur when dev->num_tc is updated, triggering oops. The
> root cause is linked to locking issues. An explanation is given in each
> of the commit logs.
>
> We had a discussion on the v1 of this series about using the xps_map
> mutex instead of the rtnl lock. While that seemed a better compromise,
> v2 showed the added complexity wasn't best for fixes. So we decided to
> go back to v1 and use the rtnl lock.
>
> Because of this, the only differences between v1 and v3 are improvements
> in the commit messages.
>
> Thanks!
> Antoine
>
> Antoine Tenart (4):
>   net-sysfs: take the rtnl lock when storing xps_cpus
>   net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
>   net-sysfs: take the rtnl lock when storing xps_rxqs
>   net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
>
>  net/core/net-sysfs.c | 65 ++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 53 insertions(+), 12 deletions(-)
>

The series looks fine to me. Not the prettiest in the case of showing
the maps, but I don't think much can be done about that since we have
to return an error type and release the rtnl_lock.

Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code
  2020-12-23 23:26 ` [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Alexander Duyck
@ 2020-12-28 21:29   ` Jakub Kicinski
  0 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2020-12-28 21:29 UTC (permalink / raw)
  To: Alexander Duyck, Antoine Tenart; +Cc: David Miller, Netdev, Paolo Abeni

On Wed, 23 Dec 2020 15:26:08 -0800 Alexander Duyck wrote:
> On Wed, Dec 23, 2020 at 1:23 PM Antoine Tenart <atenart@kernel.org> wrote:
> >
> > Hello all,
> >
> > This series fixes race conditions in the xps code, where out of bound
> > accesses can occur when dev->num_tc is updated, triggering oops. The
> > root cause is linked to locking issues. An explanation is given in each
> > of the commit logs.
> >
> > We had a discussion on the v1 of this series about using the xps_map
> > mutex instead of the rtnl lock. While that seemed a better compromise,
> > v2 showed the added complexity wasn't best for fixes. So we decided to
> > go back to v1 and use the rtnl lock.
> >
> > Because of this, the only differences between v1 and v3 are improvements
> > in the commit messages.
> >
> > Thanks!
> > Antoine
> >
> > Antoine Tenart (4):
> >   net-sysfs: take the rtnl lock when storing xps_cpus
> >   net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
> >   net-sysfs: take the rtnl lock when storing xps_rxqs
> >   net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
> >
> >  net/core/net-sysfs.c | 65 ++++++++++++++++++++++++++++++++++++--------
> >  1 file changed, 53 insertions(+), 12 deletions(-)
> >  
> 
> The series looks fine to me. Not the prettiest in the case of showing
> the maps, but I don't think much can be done about that since we have
> to return an error type and release the rtnl_lock.
> 
> Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>

Applied, thanks!

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-12-28 23:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-23 21:23 [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Antoine Tenart
2020-12-23 21:23 ` [PATCH net v3 1/4] net-sysfs: take the rtnl lock when storing xps_cpus Antoine Tenart
2020-12-23 21:23 ` [PATCH net v3 2/4] net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc Antoine Tenart
2020-12-23 21:23 ` [PATCH net v3 3/4] net-sysfs: take the rtnl lock when storing xps_rxqs Antoine Tenart
2020-12-23 21:23 ` [PATCH net v3 4/4] net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc Antoine Tenart
2020-12-23 23:26 ` [PATCH net v3 0/4] net-sysfs: fix race conditions in the xps code Alexander Duyck
2020-12-28 21:29   ` Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.