From 86348d217661c7fe4f043df444658a6a9adcff29 Mon Sep 17 00:00:00 2001 From: Erick Archer Date: Sun, 12 May 2024 18:10:27 +0200 Subject: net: prestera: Add flex arrays to some structs The "struct prestera_msg_vtcam_rule_add_req" uses a dynamically sized set of trailing elements. Specifically, it uses an array of structures of type "prestera_msg_acl_action actions_msg". The "struct prestera_msg_flood_domain_ports_set_req" also uses a dynamically sized set of trailing elements. Specifically, it uses an array of structures of type "prestera_msg_acl_action actions_msg". So, use the preferred way in the kernel declaring flexible arrays [1]. At the same time, prepare for the coming implementation by GCC and Clang of the __counted_by attribute. Flexible array members annotated with __counted_by can have their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions). In this case, it is important to note that the attribute used is specifically __counted_by_le since the counters are of type __le32. The logic does not need to change since the counters for the flexible arrays are asigned before any access to the arrays. The order in which the structure prestera_msg_vtcam_rule_add_req and the structure prestera_msg_flood_domain_ports_set_req are defined must be changed to avoid incomplete type errors. Also, avoid the open-coded arithmetic in memory allocator functions [2] using the "struct_size" macro. Moreover, the new structure members also allow us to avoid the open- coded arithmetic on pointers. So, take advantage of this refactoring accordingly. This code was detected with the help of Coccinelle, and audited and modified manually. Link: https://www.kernel.org/doc/html/next/process/deprecated.html#zero-length-and-one-element-arrays [1] Link: https://www.kernel.org/doc/html/next/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments [2] Signed-off-by: Erick Archer Reviewed-by: Simon Horman Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/AS8PR02MB7237E8469568A59795F1F0408BE12@AS8PR02MB7237.eurprd02.prod.outlook.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/marvell/prestera/prestera_hw.c | 83 ++++++++++------------ 1 file changed, 37 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.c b/drivers/net/ethernet/marvell/prestera/prestera_hw.c index fc6f7d2746e8..197198ba61b1 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_hw.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.c @@ -419,15 +419,6 @@ struct prestera_msg_vtcam_destroy_req { __le32 vtcam_id; }; -struct prestera_msg_vtcam_rule_add_req { - struct prestera_msg_cmd cmd; - __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX]; - __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX]; - __le32 vtcam_id; - __le32 prio; - __le32 n_act; -}; - struct prestera_msg_vtcam_rule_del_req { struct prestera_msg_cmd cmd; __le32 vtcam_id; @@ -471,6 +462,16 @@ struct prestera_msg_acl_action { }; }; +struct prestera_msg_vtcam_rule_add_req { + struct prestera_msg_cmd cmd; + __le32 key[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX]; + __le32 keymask[__PRESTERA_ACL_RULE_MATCH_TYPE_MAX]; + __le32 vtcam_id; + __le32 prio; + __le32 n_act; + struct prestera_msg_acl_action actions_msg[] __counted_by_le(n_act); +}; + struct prestera_msg_counter_req { struct prestera_msg_cmd cmd; __le32 client; @@ -702,12 +703,6 @@ struct prestera_msg_flood_domain_destroy_req { __le32 flood_domain_idx; }; -struct prestera_msg_flood_domain_ports_set_req { - struct prestera_msg_cmd cmd; - __le32 flood_domain_idx; - __le32 ports_num; -}; - struct prestera_msg_flood_domain_ports_reset_req { struct prestera_msg_cmd cmd; __le32 flood_domain_idx; @@ -725,6 +720,13 @@ struct prestera_msg_flood_domain_port { __le16 port_type; }; +struct prestera_msg_flood_domain_ports_set_req { + struct prestera_msg_cmd cmd; + __le32 flood_domain_idx; + __le32 ports_num; + struct prestera_msg_flood_domain_port ports[] __counted_by_le(ports_num); +}; + struct prestera_msg_mdb_create_req { struct prestera_msg_cmd cmd; __le32 flood_domain_idx; @@ -1371,23 +1373,18 @@ int prestera_hw_vtcam_rule_add(struct prestera_switch *sw, struct prestera_acl_hw_action_info *act, u8 n_act, u32 *rule_id) { - struct prestera_msg_acl_action *actions_msg; struct prestera_msg_vtcam_rule_add_req *req; struct prestera_msg_vtcam_resp resp; - void *buff; - u32 size; + size_t size; int err; u8 i; - size = sizeof(*req) + sizeof(*actions_msg) * n_act; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) + size = struct_size(req, actions_msg, n_act); + req = kzalloc(size, GFP_KERNEL); + if (!req) return -ENOMEM; - req = buff; req->n_act = __cpu_to_le32(n_act); - actions_msg = buff + sizeof(*req); /* put acl matches into the message */ memcpy(req->key, key, sizeof(req->key)); @@ -1395,7 +1392,7 @@ int prestera_hw_vtcam_rule_add(struct prestera_switch *sw, /* put acl actions into the message */ for (i = 0; i < n_act; i++) { - err = prestera_acl_rule_add_put_action(&actions_msg[i], + err = prestera_acl_rule_add_put_action(&req->actions_msg[i], &act[i]); if (err) goto free_buff; @@ -1411,7 +1408,7 @@ int prestera_hw_vtcam_rule_add(struct prestera_switch *sw, *rule_id = __le32_to_cpu(resp.rule_id); free_buff: - kfree(buff); + kfree(req); return err; } @@ -2461,14 +2458,13 @@ int prestera_hw_flood_domain_ports_set(struct prestera_flood_domain *domain) { struct prestera_flood_domain_port *flood_domain_port; struct prestera_msg_flood_domain_ports_set_req *req; - struct prestera_msg_flood_domain_port *ports; struct prestera_switch *sw = domain->sw; struct prestera_port *port; u32 ports_num = 0; - int buf_size; - void *buff; + size_t buf_size; u16 lag_id; int err; + int i = 0; list_for_each_entry(flood_domain_port, &domain->flood_domain_port_list, flood_domain_port_node) @@ -2477,15 +2473,11 @@ int prestera_hw_flood_domain_ports_set(struct prestera_flood_domain *domain) if (!ports_num) return -EINVAL; - buf_size = sizeof(*req) + sizeof(*ports) * ports_num; - - buff = kmalloc(buf_size, GFP_KERNEL); - if (!buff) + buf_size = struct_size(req, ports, ports_num); + req = kmalloc(buf_size, GFP_KERNEL); + if (!req) return -ENOMEM; - req = buff; - ports = buff + sizeof(*req); - req->flood_domain_idx = __cpu_to_le32(domain->idx); req->ports_num = __cpu_to_le32(ports_num); @@ -2494,31 +2486,30 @@ int prestera_hw_flood_domain_ports_set(struct prestera_flood_domain *domain) if (netif_is_lag_master(flood_domain_port->dev)) { if (prestera_lag_id(sw, flood_domain_port->dev, &lag_id)) { - kfree(buff); + kfree(req); return -EINVAL; } - ports->port_type = + req->ports[i].port_type = __cpu_to_le16(PRESTERA_HW_FLOOD_DOMAIN_PORT_TYPE_LAG); - ports->lag_id = __cpu_to_le16(lag_id); + req->ports[i].lag_id = __cpu_to_le16(lag_id); } else { port = prestera_port_dev_lower_find(flood_domain_port->dev); - ports->port_type = + req->ports[i].port_type = __cpu_to_le16(PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT); - ports->dev_num = __cpu_to_le32(port->dev_id); - ports->port_num = __cpu_to_le32(port->hw_id); + req->ports[i].dev_num = __cpu_to_le32(port->dev_id); + req->ports[i].port_num = __cpu_to_le32(port->hw_id); } - ports->vid = __cpu_to_le16(flood_domain_port->vid); - - ports++; + req->ports[i].vid = __cpu_to_le16(flood_domain_port->vid); + i++; } err = prestera_cmd(sw, PRESTERA_CMD_TYPE_FLOOD_DOMAIN_PORTS_SET, &req->cmd, buf_size); - kfree(buff); + kfree(req); return err; } -- cgit v1.2.3