Skip to content

Commit 4314f9f

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Avoid using extended string-buffers sizes if not necessary
Commit b260fcc ("firmware: arm_scmi: Add SCMI v3.1 protocol extended names support") moved all the name string buffers to use the extended buffer size of 64 instead of the required 16 bytes. While that should be fine if the firmware terminates the string before 16 bytes, there is possibility of copying random data if the name is not NULL terminated by the firmware. SCMI base protocol agent_name/vendor_id/sub_vendor_id are defined by the specification as NULL-terminated ASCII strings up to 16-bytes in length. The underlying buffers and message descriptors are currently bigger than needed; resize them to fit only the strictly needed 16 bytes to avoid any possible leaks when reading data from the firmware. Change the size argument of strlcpy to use SCMI_SHORT_NAME_MAX_SIZE always when dealing with short domain names, so as to limit the possibility that an ill-formed non-NULL terminated short reply from the SCMI platform firmware can leak stale content laying in the underlying transport shared memory area. While at that, convert all strings handling routines to use the preferred strscpy. Link: https://lore.kernel.org/r/[email protected] Fixes: b260fcc ("firmware: arm_scmi: Add SCMI v3.1 protocol extended names support") Signed-off-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 8e60294 commit 4314f9f

File tree

9 files changed

+16
-17
lines changed

9 files changed

+16
-17
lines changed

drivers/firmware/arm_scmi/base.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct scmi_msg_resp_base_attributes {
3636

3737
struct scmi_msg_resp_base_discover_agent {
3838
__le32 agent_id;
39-
u8 name[SCMI_MAX_STR_SIZE];
39+
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
4040
};
4141

4242

@@ -119,7 +119,7 @@ scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor)
119119

120120
ret = ph->xops->do_xfer(ph, t);
121121
if (!ret)
122-
memcpy(vendor_id, t->rx.buf, size);
122+
strscpy(vendor_id, t->rx.buf, size);
123123

124124
ph->xops->xfer_put(ph, t);
125125

@@ -276,7 +276,7 @@ static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph,
276276
ret = ph->xops->do_xfer(ph, t);
277277
if (!ret) {
278278
agent_info = t->rx.buf;
279-
strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE);
279+
strscpy(name, agent_info->name, SCMI_SHORT_NAME_MAX_SIZE);
280280
}
281281

282282
ph->xops->xfer_put(ph, t);
@@ -375,7 +375,7 @@ static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
375375
int id, ret;
376376
u8 *prot_imp;
377377
u32 version;
378-
char name[SCMI_MAX_STR_SIZE];
378+
char name[SCMI_SHORT_NAME_MAX_SIZE];
379379
struct device *dev = ph->dev;
380380
struct scmi_revision_info *rev = scmi_revision_area_get(ph);
381381

drivers/firmware/arm_scmi/clock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
153153
if (!ret) {
154154
u32 latency = 0;
155155
attributes = le32_to_cpu(attr->attributes);
156-
strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE);
156+
strscpy(clk->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
157157
/* clock_enable_latency field is present only since SCMI v3.1 */
158158
if (PROTOCOL_REV_MAJOR(version) >= 0x2)
159159
latency = le32_to_cpu(attr->clock_enable_latency);

drivers/firmware/arm_scmi/perf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
252252
dom_info->mult_factor =
253253
(dom_info->sustained_freq_khz * 1000) /
254254
dom_info->sustained_perf_level;
255-
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
255+
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
256256
}
257257

258258
ph->xops->xfer_put(ph, t);

drivers/firmware/arm_scmi/power.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph,
122122
dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags);
123123
dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
124124
dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
125-
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
125+
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
126126
}
127127
ph->xops->xfer_put(ph, t);
128128

drivers/firmware/arm_scmi/protocols.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
#include <asm/unaligned.h>
2626

27-
#define SCMI_SHORT_NAME_MAX_SIZE 16
28-
2927
#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
3028
#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
3129
#define PROTOCOL_REV_MAJOR(x) ((u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x))))

drivers/firmware/arm_scmi/reset.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
116116
dom_info->latency_us = le32_to_cpu(attr->latency);
117117
if (dom_info->latency_us == U32_MAX)
118118
dom_info->latency_us = 0;
119-
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
119+
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
120120
}
121121

122122
ph->xops->xfer_put(ph, t);

drivers/firmware/arm_scmi/sensors.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ iter_axes_desc_process_response(const struct scmi_protocol_handle *ph,
412412
attrh = le32_to_cpu(adesc->attributes_high);
413413
a->scale = S32_EXT(SENSOR_SCALE(attrh));
414414
a->type = SENSOR_TYPE(attrh);
415-
strscpy(a->name, adesc->name, SCMI_MAX_STR_SIZE);
415+
strscpy(a->name, adesc->name, SCMI_SHORT_NAME_MAX_SIZE);
416416

417417
if (a->extended_attrs) {
418418
unsigned int ares = le32_to_cpu(adesc->resolution);
@@ -634,7 +634,7 @@ iter_sens_descr_process_response(const struct scmi_protocol_handle *ph,
634634
SUPPORTS_AXIS(attrh) ?
635635
SENSOR_AXIS_NUMBER(attrh) : 0,
636636
SCMI_MAX_NUM_SENSOR_AXIS);
637-
strscpy(s->name, sdesc->name, SCMI_MAX_STR_SIZE);
637+
strscpy(s->name, sdesc->name, SCMI_SHORT_NAME_MAX_SIZE);
638638

639639
/*
640640
* If supported overwrite short name with the extended

drivers/firmware/arm_scmi/voltage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph,
233233
v = vinfo->domains + dom;
234234
v->id = dom;
235235
attributes = le32_to_cpu(resp_dom->attr);
236-
strlcpy(v->name, resp_dom->name, SCMI_MAX_STR_SIZE);
236+
strscpy(v->name, resp_dom->name, SCMI_SHORT_NAME_MAX_SIZE);
237237

238238
/*
239239
* If supported overwrite short name with the extended one;

include/linux/scmi_protocol.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#include <linux/notifier.h>
1414
#include <linux/types.h>
1515

16-
#define SCMI_MAX_STR_SIZE 64
17-
#define SCMI_MAX_NUM_RATES 16
16+
#define SCMI_MAX_STR_SIZE 64
17+
#define SCMI_SHORT_NAME_MAX_SIZE 16
18+
#define SCMI_MAX_NUM_RATES 16
1819

1920
/**
2021
* struct scmi_revision_info - version information structure
@@ -36,8 +37,8 @@ struct scmi_revision_info {
3637
u8 num_protocols;
3738
u8 num_agents;
3839
u32 impl_ver;
39-
char vendor_id[SCMI_MAX_STR_SIZE];
40-
char sub_vendor_id[SCMI_MAX_STR_SIZE];
40+
char vendor_id[SCMI_SHORT_NAME_MAX_SIZE];
41+
char sub_vendor_id[SCMI_SHORT_NAME_MAX_SIZE];
4142
};
4243

4344
struct scmi_clock_info {

0 commit comments

Comments
 (0)