Skip to contentSkip to conversation

RDMA/core: Use size_{add,mul}() in calls to struct_size()

PATCH Superseded Gustavo A. R. Silva 4 participants 7 messages Sep 12, 2023 – Sep 18, 2023 InfiniBand

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 RDMA/core: Use size_{add,mul}() in calls to struct_size()

Harden calls to struct_size() with size_add() and size_mul().

Fixes 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes")
Fixes a4676388e2e2 ("RDMA/core: Simplify how the gid_attrs sysfs is created")

---
Changes in v2:
- Update changelog text: remove the part about binary differences (it was added by mistake).

 drivers/infiniband/core/sysfs.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/infiniband/core/sysfs.c +5 -5
index ee59d7391568..ec5efdc16660 100644
@@ -903,7 +903,7 @@ alloc_hw_stats_device(struct ib_device *ibdev)
 	 * Two extra attribue elements here, one for the lifespan entry and
 	 * one to NULL terminate the list for the sysfs core code
 	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
 		       GFP_KERNEL);
 	if (!data)
 		goto err_free_stats;
@@ -1009,7 +1009,7 @@ alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)
 	 * Two extra attribue elements here, one for the lifespan entry and
 	 * one to NULL terminate the list for the sysfs core code
 	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
 		       GFP_KERNEL);
 	if (!data)
 		goto err_free_stats;
@@ -1140,7 +1140,7 @@ static int setup_gid_attrs(struct ib_port *port,
 	int ret;
 
 	gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,
-					     attr->gid_tbl_len * 2),
+					     size_mul(attr->gid_tbl_len, 2)),
 				 GFP_KERNEL);
 	if (!gid_attr_group)
 		return -ENOMEM;
@@ -1205,8 +1205,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,
 	int ret;
 
 	p = kvzalloc(struct_size(p, attrs_list,
-				attr->gid_tbl_len + attr->pkey_tbl_len),
-		    GFP_KERNEL);
+				size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),
+		     GFP_KERNEL);
 	if (!p)
 		return ERR_PTR(-ENOMEM);
 	p->ibdev = device;
Signature · 1 line
2.34.1
Reviewed-by on v2 1/1
#1 lore raw
Quoted 1 line · Gustavo A. R. Silva

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Quoted 4 lines
Fixes 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes")
Fixes a4676388e2e2 ("RDMA/core: Simplify how the gid_attrs sysfs is created")

-Kees

Quoted 53 lines

---
Changes in v2:
- Update changelog text: remove the part about binary differences (it was added by mistake).

 drivers/infiniband/core/sysfs.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/infiniband/core/sysfs.c +5 -5
index ee59d7391568..ec5efdc16660 100644
@@ -903,7 +903,7 @@ alloc_hw_stats_device(struct ib_device *ibdev)
 	 * Two extra attribue elements here, one for the lifespan entry and
 	 * one to NULL terminate the list for the sysfs core code
 	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
 		       GFP_KERNEL);
 	if (!data)
 		goto err_free_stats;
@@ -1009,7 +1009,7 @@ alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)
 	 * Two extra attribue elements here, one for the lifespan entry and
 	 * one to NULL terminate the list for the sysfs core code
 	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
 		       GFP_KERNEL);
 	if (!data)
 		goto err_free_stats;
@@ -1140,7 +1140,7 @@ static int setup_gid_attrs(struct ib_port *port,
 	int ret;
 
 	gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,
-					     attr->gid_tbl_len * 2),
+					     size_mul(attr->gid_tbl_len, 2)),
 				 GFP_KERNEL);
 	if (!gid_attr_group)
 		return -ENOMEM;
@@ -1205,8 +1205,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,
 	int ret;
 
 	p = kvzalloc(struct_size(p, attrs_list,
-				attr->gid_tbl_len + attr->pkey_tbl_len),
-		    GFP_KERNEL);
+				size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),
+		     GFP_KERNEL);
 	if (!p)
 		return ERR_PTR(-ENOMEM);
 	p->ibdev = device;
Signature · 1 line
2.34.1
Signature · 1 line
Kees Cook
#2 lore raw
Quoted 5 lines · Kees Cook
Quoted 1 line · Gustavo A. R. Silva

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Yep; I have another patch where I explain this in similar terms.

I'll send it, shortly.

Quoted 7 lines
Quoted 5 lines
Fixes 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes")
Fixes a4676388e2e2 ("RDMA/core: Simplify how the gid_attrs sysfs is created")

Thanks!

--
Gustavo

Quoted 57 lines

-Kees

Quoted 53 lines

---
Changes in v2:
- Update changelog text: remove the part about binary differences (it was added by mistake).

  drivers/infiniband/core/sysfs.c | 10 +++++-----
  1 file changed, 5 insertions(+), 5 deletions(-)
drivers/infiniband/core/sysfs.c +5 -5
index ee59d7391568..ec5efdc16660 100644
@@ -903,7 +903,7 @@ alloc_hw_stats_device(struct ib_device *ibdev)
  	 * Two extra attribue elements here, one for the lifespan entry and
  	 * one to NULL terminate the list for the sysfs core code
  	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
  		       GFP_KERNEL);
  	if (!data)
  		goto err_free_stats;
@@ -1009,7 +1009,7 @@ alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)
  	 * Two extra attribue elements here, one for the lifespan entry and
  	 * one to NULL terminate the list for the sysfs core code
  	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
  		       GFP_KERNEL);
  	if (!data)
  		goto err_free_stats;
@@ -1140,7 +1140,7 @@ static int setup_gid_attrs(struct ib_port *port,
  	int ret;
 
  	gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,
-					     attr->gid_tbl_len * 2),
+					     size_mul(attr->gid_tbl_len, 2)),
  				 GFP_KERNEL);
  	if (!gid_attr_group)
  		return -ENOMEM;
@@ -1205,8 +1205,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,
  	int ret;
 
  	p = kvzalloc(struct_size(p, attrs_list,
-				attr->gid_tbl_len + attr->pkey_tbl_len),
-		    GFP_KERNEL);
+				size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),
+		     GFP_KERNEL);
  	if (!p)
  		return ERR_PTR(-ENOMEM);
  	p->ibdev = device;
Signature · 1 line
2.34.1
#3 lore raw
Quoted 4 lines · Gustavo A. R. Silva
Quoted 1 line · Kees Cook

On Mon, Sep 11, 2023 at 05:27:59PM -0600, Gustavo A. R. Silva wrote:

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Yep; I have another patch where I explain this in similar terms.

I'll send it, shortly.

You missed other places with similar arithmetic.
drivers/infiniband/core/device.c: pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata,
drivers/infiniband/core/device.c- rdma_end_port(device) + 1),
drivers/infiniband/core/device.c- GFP_KERNEL);

drivers/infiniband/core/sa_query.c: sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
drivers/infiniband/core/user_mad.c: umad_dev = kzalloc(struct_size(umad_dev, ports, e - s + 1), GFP_KERNEL);

Thanks

Quoted 69 lines
Quoted 8 lines
Quoted 6 lines
Fixes 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes")
Fixes a4676388e2e2 ("RDMA/core: Simplify how the gid_attrs sysfs is created")

Thanks!

--
Gustavo

Quoted 55 lines

-Kees

Quoted 51 lines

---
Changes in v2:
- Update changelog text: remove the part about binary differences (it was added by mistake).

  drivers/infiniband/core/sysfs.c | 10 +++++-----
  1 file changed, 5 insertions(+), 5 deletions(-)
drivers/infiniband/core/sysfs.c +5 -5
index ee59d7391568..ec5efdc16660 100644
@@ -903,7 +903,7 @@ alloc_hw_stats_device(struct ib_device *ibdev)
  	 * Two extra attribue elements here, one for the lifespan entry and
  	 * one to NULL terminate the list for the sysfs core code
  	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
  		       GFP_KERNEL);
  	if (!data)
  		goto err_free_stats;
@@ -1009,7 +1009,7 @@ alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)
  	 * Two extra attribue elements here, one for the lifespan entry and
  	 * one to NULL terminate the list for the sysfs core code
  	 */
-	data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
+	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
  		       GFP_KERNEL);
  	if (!data)
  		goto err_free_stats;
@@ -1140,7 +1140,7 @@ static int setup_gid_attrs(struct ib_port *port,
  	int ret;
  	gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,
-					     attr->gid_tbl_len * 2),
+					     size_mul(attr->gid_tbl_len, 2)),
  				 GFP_KERNEL);
  	if (!gid_attr_group)
  		return -ENOMEM;
@@ -1205,8 +1205,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,
  	int ret;
  	p = kvzalloc(struct_size(p, attrs_list,
-				attr->gid_tbl_len + attr->pkey_tbl_len),
-		    GFP_KERNEL);
+				size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),
+		     GFP_KERNEL);
  	if (!p)
  		return ERR_PTR(-ENOMEM);
  	p->ibdev = device;
Signature · 1 line
2.34.1
#4 lore raw
Quoted 14 lines · Leon Romanovsky
Quoted 4 lines · Gustavo A. R. Silva
Quoted 1 line · Kees Cook

On Mon, Sep 11, 2023 at 05:27:59PM -0600, Gustavo A. R. Silva wrote:

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Yep; I have another patch where I explain this in similar terms.

I'll send it, shortly.

Quoted 7 lines

You missed other places with similar arithmetic.
drivers/infiniband/core/device.c: pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata,
drivers/infiniband/core/device.c- rdma_end_port(device) + 1),
drivers/infiniband/core/device.c- GFP_KERNEL);

drivers/infiniband/core/sa_query.c: sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
drivers/infiniband/core/user_mad.c: umad_dev = kzalloc(struct_size(umad_dev, ports, e - s + 1), GFP_KERNEL);

I haven't sent all my patches.

--
Gustavo

#5 lore raw
Quoted 22 lines · Gustavo A. R. Silva
Quoted 19 lines · Leon Romanovsky
Quoted 4 lines · Gustavo A. R. Silva
Quoted 1 line · Kees Cook

On Mon, Sep 11, 2023 at 05:27:59PM -0600, Gustavo A. R. Silva wrote:

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Yep; I have another patch where I explain this in similar terms.

I'll send it, shortly.

You missed other places with similar arithmetic.
drivers/infiniband/core/device.c: pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata,
drivers/infiniband/core/device.c- rdma_end_port(device) + 1),
drivers/infiniband/core/device.c- GFP_KERNEL);

Quoted 4 lines
Quoted 2 lines

drivers/infiniband/core/sa_query.c: sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
drivers/infiniband/core/user_mad.c: umad_dev = kzalloc(struct_size(umad_dev, ports, e - s + 1), GFP_KERNEL);

I haven't sent all my patches.

Please sent one patch for whole drivers/infiniband/core/ folder as your
title: "RDMA/core ..." suggests.

Thanks

Quoted 3 lines

--
Gustavo

#6 lore raw
Quoted 23 lines · Leon Romanovsky
Quoted 22 lines · Gustavo A. R. Silva
Quoted 19 lines · Leon Romanovsky
Quoted 4 lines · Gustavo A. R. Silva
Quoted 1 line · Kees Cook

On Mon, Sep 11, 2023 at 05:27:59PM -0600, Gustavo A. R. Silva wrote:

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Harden calls to struct_size() with size_add() and size_mul().

Specifically, make sure that open-coded arithmetic cannot cause an overflow/wraparound. (i.e. it will stay saturated at SIZE_MAX.)

Yep; I have another patch where I explain this in similar terms.

I'll send it, shortly.

You missed other places with similar arithmetic.
drivers/infiniband/core/device.c: pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata,
drivers/infiniband/core/device.c- rdma_end_port(device) + 1),
drivers/infiniband/core/device.c- GFP_KERNEL);

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

drivers/infiniband/core/sa_query.c: sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
drivers/infiniband/core/user_mad.c: umad_dev = kzalloc(struct_size(umad_dev, ports, e - s + 1), GFP_KERNEL);

I haven't sent all my patches.

Please sent one patch for whole drivers/infiniband/core/ folder as your
title: "RDMA/core ..." suggests.

OK. Done:

https://lore.kernel.org/linux-hardening/ZQdt4NsJFwwOYxUR@work/

Thanks
--
Gustavo