Message ID | 20240923002249.it.617-kees@kernel.org (mailing list archive) |
---|---|
State | Mainlined |
Commit | 63cafaf47a834fa15d80238f9d8181d32931be17 |
Headers | show |
Series | [v2] HID: ishtp-hid-client: replace fake-flex arrays with flex-array members | expand |
On Sun, 2024-09-22 at 17:22 -0700, Kees Cook wrote: > From: Erick Archer <erick.archer@outlook.com> > > One-element arrays as fake flex arrays are deprecated[1] as the > kernel > has switched to C99 flexible-array members instead. This case, > however, > has more complexity because it is a flexible array of flexible arrays > and this patch needs to be ready to enable the new compiler flag > -Wflex-array-member-not-at-end (coming in GCC-14) globally. > > So, define a new struct type for the single reports: > > struct report { > uint16_t size; > struct hostif_msg_hdr msg; > } __packed; > > but without the payload (flex array) in it. And add this payload to > the > "hostif_msg" structure. This way, in the "report_list" structure we > can > declare a flex array of single reports which now do not contain > another > flex array. > > struct report_list { > [...] > struct report reports[]; > } __packed; > > Therefore, the "struct hostif_msg" is now made up of a header and a > payload. And the "struct report" uses only the "hostif_msg" header. > The perfect solution would be for the "report" structure to use the > whole "hostif_msg" structure but this is not possible due to nested > flexible arrays. Anyway, the end result is equivalent since this > patch > does attempt to change the behaviour of the code. > > Now as well, we have more clarity after the cast from the raw bytes > to > the new structures. Refactor the code accordingly to use the new > structures. > > Also, use "container_of()" whenever we need to retrieve a pointer to > the flexible structure, through which we can access the flexible > array > if needed. > > Link: > https://www.kernel.org/doc/html/next/process/deprecated.html#zero-length-and-one-element-arrays > [1] > Closes: https://github.com/KSPP/linux/issues/333 > Signed-off-by: Erick Archer <erick.archer@outlook.com> > Link: > https://lore.kernel.org/r/AS8PR02MB723760CB93942370E92F00638BF72@AS8PR02MB7237.eurprd02.prod.outlook.com > [kees: tweaked commit log and dropped struct_size() uses] > Signed-off-by: Kees Cook <kees@kernel.org> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> > --- > v2: - update based on feedback > rfc: > https://lore.kernel.org/lkml/AS8PR02MB723760CB93942370E92F00638BF72@AS8PR02MB7237.eurprd02.prod.outlook.com/ > --- > drivers/hid/intel-ish-hid/ishtp-hid-client.c | 25 ++++++++++-------- > -- > drivers/hid/intel-ish-hid/ishtp-hid.h | 11 +++++---- > 2 files changed, 19 insertions(+), 17 deletions(-) > > diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c > b/drivers/hid/intel-ish-hid/ishtp-hid-client.c > index fbd4f8ea1951..cb04cd1d980b 100644 > --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c > +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c > @@ -70,10 +70,10 @@ static void process_recv(struct ishtp_cl > *hid_ishtp_cl, void *recv_buf, > unsigned char *payload; > struct device_info *dev_info; > int i, j; > - size_t payload_len, total_len, cur_pos, raw_len; > + size_t payload_len, total_len, cur_pos, raw_len, msg_len; > int report_type; > struct report_list *reports_list; > - char *reports; > + struct report *report; > size_t report_len; > struct ishtp_cl_data *client_data = > ishtp_get_client_data(hid_ishtp_cl); > int curr_hid_dev = client_data->cur_hid_dev; > @@ -280,14 +280,13 @@ static void process_recv(struct ishtp_cl > *hid_ishtp_cl, void *recv_buf, > case HOSTIF_PUBLISH_INPUT_REPORT_LIST: > report_type = HID_INPUT_REPORT; > reports_list = (struct report_list *)payload; > - reports = (char *)reports_list->reports; > + report = reports_list->reports; > > for (j = 0; j < reports_list->num_of_reports; > j++) { > - recv_msg = (struct hostif_msg > *)(reports + > - sizeof(uint16_t)); > - report_len = *(uint16_t *)reports; > - payload = reports + sizeof(uint16_t) > + > - sizeof(struct > hostif_msg_hdr); > + recv_msg = container_of(&report->msg, > + struct > hostif_msg, hdr); > + report_len = report->size; > + payload = recv_msg->payload; > payload_len = report_len - > sizeof(struct > hostif_msg_hdr); > > @@ -304,7 +303,7 @@ static void process_recv(struct ishtp_cl > *hid_ishtp_cl, void *recv_buf, > 0); > } > > - reports += sizeof(uint16_t) + > report_len; > + report += sizeof(*report) + > payload_len; > } > break; > default: > @@ -316,12 +315,12 @@ static void process_recv(struct ishtp_cl > *hid_ishtp_cl, void *recv_buf, > > } > > - if (!cur_pos && cur_pos + payload_len + > - sizeof(struct hostif_msg) < > total_len) > + msg_len = payload_len + sizeof(struct hostif_msg); > + if (!cur_pos && cur_pos + msg_len < total_len) > ++client_data->multi_packet_cnt; > > - cur_pos += payload_len + sizeof(struct hostif_msg); > - payload += payload_len + sizeof(struct hostif_msg); > + cur_pos += msg_len; > + payload += msg_len; > > } while (cur_pos < total_len); > } > diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h > b/drivers/hid/intel-ish-hid/ishtp-hid.h > index 35dddc5015b3..2bc19e8ba13e 100644 > --- a/drivers/hid/intel-ish-hid/ishtp-hid.h > +++ b/drivers/hid/intel-ish-hid/ishtp-hid.h > @@ -31,6 +31,7 @@ struct hostif_msg_hdr { > > struct hostif_msg { > struct hostif_msg_hdr hdr; > + uint8_t payload[]; > } __packed; > > struct hostif_msg_to_sensor { > @@ -52,15 +53,17 @@ struct ishtp_version { > uint16_t build; > } __packed; > > +struct report { > + uint16_t size; > + struct hostif_msg_hdr msg; > +} __packed; > + > /* struct for ISHTP aggregated input data */ > struct report_list { > uint16_t total_size; > uint8_t num_of_reports; > uint8_t flags; > - struct { > - uint16_t size_of_report; > - uint8_t report[1]; > - } __packed reports[1]; > + struct report reports[]; > } __packed; > > /* HOSTIF commands */
On Sun, 22 Sep 2024, Kees Cook wrote: > From: Erick Archer <erick.archer@outlook.com> > > One-element arrays as fake flex arrays are deprecated[1] as the kernel > has switched to C99 flexible-array members instead. This case, however, > has more complexity because it is a flexible array of flexible arrays > and this patch needs to be ready to enable the new compiler flag > -Wflex-array-member-not-at-end (coming in GCC-14) globally. > > So, define a new struct type for the single reports: > > struct report { > uint16_t size; > struct hostif_msg_hdr msg; > } __packed; > > but without the payload (flex array) in it. And add this payload to the > "hostif_msg" structure. This way, in the "report_list" structure we can > declare a flex array of single reports which now do not contain another > flex array. > > struct report_list { > [...] > struct report reports[]; > } __packed; > > Therefore, the "struct hostif_msg" is now made up of a header and a > payload. And the "struct report" uses only the "hostif_msg" header. > The perfect solution would be for the "report" structure to use the > whole "hostif_msg" structure but this is not possible due to nested > flexible arrays. Anyway, the end result is equivalent since this patch > does attempt to change the behaviour of the code. > > Now as well, we have more clarity after the cast from the raw bytes to > the new structures. Refactor the code accordingly to use the new > structures. > > Also, use "container_of()" whenever we need to retrieve a pointer to > the flexible structure, through which we can access the flexible array > if needed. > > Link: https://www.kernel.org/doc/html/next/process/deprecated.html#zero-length-and-one-element-arrays [1] > Closes: https://github.com/KSPP/linux/issues/333 > Signed-off-by: Erick Archer <erick.archer@outlook.com> > Link: https://lore.kernel.org/r/AS8PR02MB723760CB93942370E92F00638BF72@AS8PR02MB7237.eurprd02.prod.outlook.com > [kees: tweaked commit log and dropped struct_size() uses] > Signed-off-by: Kees Cook <kees@kernel.org> > --- > v2: - update based on feedback > rfc: https://lore.kernel.org/lkml/AS8PR02MB723760CB93942370E92F00638BF72@AS8PR02MB7237.eurprd02.prod.outlook.com/ Applied, thanks.
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c index fbd4f8ea1951..cb04cd1d980b 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c @@ -70,10 +70,10 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, unsigned char *payload; struct device_info *dev_info; int i, j; - size_t payload_len, total_len, cur_pos, raw_len; + size_t payload_len, total_len, cur_pos, raw_len, msg_len; int report_type; struct report_list *reports_list; - char *reports; + struct report *report; size_t report_len; struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl); int curr_hid_dev = client_data->cur_hid_dev; @@ -280,14 +280,13 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, case HOSTIF_PUBLISH_INPUT_REPORT_LIST: report_type = HID_INPUT_REPORT; reports_list = (struct report_list *)payload; - reports = (char *)reports_list->reports; + report = reports_list->reports; for (j = 0; j < reports_list->num_of_reports; j++) { - recv_msg = (struct hostif_msg *)(reports + - sizeof(uint16_t)); - report_len = *(uint16_t *)reports; - payload = reports + sizeof(uint16_t) + - sizeof(struct hostif_msg_hdr); + recv_msg = container_of(&report->msg, + struct hostif_msg, hdr); + report_len = report->size; + payload = recv_msg->payload; payload_len = report_len - sizeof(struct hostif_msg_hdr); @@ -304,7 +303,7 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, 0); } - reports += sizeof(uint16_t) + report_len; + report += sizeof(*report) + payload_len; } break; default: @@ -316,12 +315,12 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, } - if (!cur_pos && cur_pos + payload_len + - sizeof(struct hostif_msg) < total_len) + msg_len = payload_len + sizeof(struct hostif_msg); + if (!cur_pos && cur_pos + msg_len < total_len) ++client_data->multi_packet_cnt; - cur_pos += payload_len + sizeof(struct hostif_msg); - payload += payload_len + sizeof(struct hostif_msg); + cur_pos += msg_len; + payload += msg_len; } while (cur_pos < total_len); } diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h b/drivers/hid/intel-ish-hid/ishtp-hid.h index 35dddc5015b3..2bc19e8ba13e 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid.h +++ b/drivers/hid/intel-ish-hid/ishtp-hid.h @@ -31,6 +31,7 @@ struct hostif_msg_hdr { struct hostif_msg { struct hostif_msg_hdr hdr; + uint8_t payload[]; } __packed; struct hostif_msg_to_sensor { @@ -52,15 +53,17 @@ struct ishtp_version { uint16_t build; } __packed; +struct report { + uint16_t size; + struct hostif_msg_hdr msg; +} __packed; + /* struct for ISHTP aggregated input data */ struct report_list { uint16_t total_size; uint8_t num_of_reports; uint8_t flags; - struct { - uint16_t size_of_report; - uint8_t report[1]; - } __packed reports[1]; + struct report reports[]; } __packed; /* HOSTIF commands */