Commit c1ddb297 authored by Gustavo A. R. Silva's avatar Gustavo A. R. Silva Committed by Bjorn Andersson

rpmsg: glink: Avoid -Wflex-array-member-not-at-end warnings

-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.

So, in order to avoid ending up with a flexible-array member in the
middle of multiple other structs, we use the `__struct_group()`
helper to create a new tagged `struct glink_msg_hdr`. This structure
groups together all the members of the flexible `struct glink_msg`
except the flexible array.

As a result, the array is effectively separated from the rest of the
members without modifying the memory layout of the flexible structure.
We then change the type of the middle struct members currently causing
trouble from `struct glink_msg` to `struct glink_msg_hdr`.

We also want to ensure that when new members need to be added to the
flexible structure, they are always included within the newly created
tagged struct. For this, we use `static_assert()`. This ensures that the
memory layout for both the flexible structure and the new tagged struct
is the same after any changes.

This approach avoids having to implement `struct glink_msg_hdr` as a
completely separate structure, thus preventing having to maintain two
independent but basically identical structures, closing the door to
potential bugs in the future.

We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure, through which we can access the flexible-array
member, if necessary.

Additionally, we use the `DEFINE_RAW_FLEX()` helper for an on-stack
definition of a flexible structure where the size for the flexible-array
member is known at compile-time.

So, with these changes, fix the following warnings:
drivers/rpmsg/qcom_glink_native.c:51:26: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/rpmsg/qcom_glink_native.c:459:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/rpmsg/qcom_glink_native.c:846:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/rpmsg/qcom_glink_native.c:968:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/rpmsg/qcom_glink_native.c:1380:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: default avatarGustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: default avatarKees Cook <kees@kernel.org>
Link: https://lore.kernel.org/r/ZrOQa2gew5yadyt3@cuteSigned-off-by: default avatarBjorn Andersson <andersson@kernel.org>
parent 34f79c11
...@@ -33,11 +33,16 @@ ...@@ -33,11 +33,16 @@
#define RPM_GLINK_CID_MAX 65536 #define RPM_GLINK_CID_MAX 65536
struct glink_msg { struct glink_msg {
__le16 cmd; /* New members MUST be added within the __struct_group() macro below. */
__le16 param1; __struct_group(glink_msg_hdr, hdr, __packed,
__le32 param2; __le16 cmd;
__le16 param1;
__le32 param2;
);
u8 data[]; u8 data[];
} __packed; } __packed;
static_assert(offsetof(struct glink_msg, data) == sizeof(struct glink_msg_hdr),
"struct member likely outside of __struct_group()");
/** /**
* struct glink_defer_cmd - deferred incoming control message * struct glink_defer_cmd - deferred incoming control message
...@@ -51,7 +56,7 @@ struct glink_msg { ...@@ -51,7 +56,7 @@ struct glink_msg {
struct glink_defer_cmd { struct glink_defer_cmd {
struct list_head node; struct list_head node;
struct glink_msg msg; struct glink_msg_hdr msg;
u8 data[]; u8 data[];
}; };
...@@ -475,12 +480,9 @@ static void qcom_glink_intent_req_abort(struct glink_channel *channel) ...@@ -475,12 +480,9 @@ static void qcom_glink_intent_req_abort(struct glink_channel *channel)
static int qcom_glink_send_open_req(struct qcom_glink *glink, static int qcom_glink_send_open_req(struct qcom_glink *glink,
struct glink_channel *channel) struct glink_channel *channel)
{ {
struct { DEFINE_RAW_FLEX(struct glink_msg, req, data, GLINK_NAME_SIZE);
struct glink_msg msg;
u8 name[GLINK_NAME_SIZE];
} __packed req;
int name_len = strlen(channel->name) + 1; int name_len = strlen(channel->name) + 1;
int req_len = ALIGN(sizeof(req.msg) + name_len, 8); int req_len = ALIGN(sizeof(*req) + name_len, 8);
int ret; int ret;
unsigned long flags; unsigned long flags;
...@@ -496,15 +498,15 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink, ...@@ -496,15 +498,15 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink,
channel->lcid = ret; channel->lcid = ret;
req.msg.cmd = cpu_to_le16(GLINK_CMD_OPEN); req->cmd = cpu_to_le16(GLINK_CMD_OPEN);
req.msg.param1 = cpu_to_le16(channel->lcid); req->param1 = cpu_to_le16(channel->lcid);
req.msg.param2 = cpu_to_le32(name_len); req->param2 = cpu_to_le32(name_len);
strcpy(req.name, channel->name); strcpy(req->data, channel->name);
trace_qcom_glink_cmd_open_tx(glink->label, channel->name, trace_qcom_glink_cmd_open_tx(glink->label, channel->name,
channel->lcid, channel->rcid); channel->lcid, channel->rcid);
ret = qcom_glink_tx(glink, &req, req_len, NULL, 0, true); ret = qcom_glink_tx(glink, req, req_len, NULL, 0, true);
if (ret) if (ret)
goto remove_idr; goto remove_idr;
...@@ -879,7 +881,9 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) ...@@ -879,7 +881,9 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra)
INIT_LIST_HEAD(&dcmd->node); INIT_LIST_HEAD(&dcmd->node);
qcom_glink_rx_peek(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); qcom_glink_rx_peek(glink,
container_of(&dcmd->msg, struct glink_msg, hdr), 0,
sizeof(dcmd->msg) + extra);
spin_lock(&glink->rx_lock); spin_lock(&glink->rx_lock);
list_add_tail(&dcmd->node, &glink->rx_queue); list_add_tail(&dcmd->node, &glink->rx_queue);
...@@ -896,7 +900,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) ...@@ -896,7 +900,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
struct glink_core_rx_intent *intent; struct glink_core_rx_intent *intent;
struct glink_channel *channel; struct glink_channel *channel;
struct { struct {
struct glink_msg msg; struct glink_msg_hdr msg;
__le32 chunk_size; __le32 chunk_size;
__le32 left_size; __le32 left_size;
} __packed hdr; } __packed hdr;
...@@ -1030,7 +1034,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink, ...@@ -1030,7 +1034,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
}; };
struct { struct {
struct glink_msg msg; struct glink_msg_hdr msg;
struct intent_pair intents[]; struct intent_pair intents[];
} __packed * msg; } __packed * msg;
...@@ -1459,7 +1463,7 @@ static int __qcom_glink_send(struct glink_channel *channel, ...@@ -1459,7 +1463,7 @@ static int __qcom_glink_send(struct glink_channel *channel,
struct glink_core_rx_intent *tmp; struct glink_core_rx_intent *tmp;
int iid = 0; int iid = 0;
struct { struct {
struct glink_msg msg; struct glink_msg_hdr msg;
__le32 chunk_size; __le32 chunk_size;
__le32 left_size; __le32 left_size;
} __packed req; } __packed req;
...@@ -1781,7 +1785,7 @@ static void qcom_glink_work(struct work_struct *work) ...@@ -1781,7 +1785,7 @@ static void qcom_glink_work(struct work_struct *work)
list_del(&dcmd->node); list_del(&dcmd->node);
spin_unlock_irqrestore(&glink->rx_lock, flags); spin_unlock_irqrestore(&glink->rx_lock, flags);
msg = &dcmd->msg; msg = container_of(&dcmd->msg, struct glink_msg, hdr);
cmd = le16_to_cpu(msg->cmd); cmd = le16_to_cpu(msg->cmd);
param1 = le16_to_cpu(msg->param1); param1 = le16_to_cpu(msg->param1);
param2 = le32_to_cpu(msg->param2); param2 = le32_to_cpu(msg->param2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment