Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
net: prestera: Add flex arrays to some structs
Browse files Browse the repository at this point in the history
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 <erick.archer@outlook.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/AS8PR02MB7237E8469568A59795F1F0408BE12@AS8PR02MB7237.eurprd02.prod.outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Erick Archer authored and kuba-moo committed May 14, 2024
1 parent a6fb986 commit 86348d2
Showing 1 changed file with 37 additions and 46 deletions.
83 changes: 37 additions & 46 deletions drivers/net/ethernet/marvell/prestera/prestera_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -1371,31 +1373,26 @@ 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));
memcpy(req->keymask, keymask, sizeof(req->keymask));

/* 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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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);

Expand All @@ -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;
}
Expand Down

0 comments on commit 86348d2

Please sign in to comment.