Skip to content

Commit

Permalink
scst: Replace all strlcpy() with strscpy()
Browse files Browse the repository at this point in the history
strlcpy() reads the entire source buffer first. This read may exceed the
destination size limit. This is both inefficient and can lead to linear
read overflows if a source string is not NULL-terminated [1].

[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
  • Loading branch information
lnocturno committed Jul 19, 2023
1 parent 16a17c2 commit bc9ec6f
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 63 deletions.
2 changes: 1 addition & 1 deletion iscsi-scst/kernel/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid,

target->tid = info->tid = tid;

strlcpy(target->name, name, sizeof(target->name));
strscpy(target->name, name, sizeof(target->name));

mutex_init(&target->target_mutex);
INIT_LIST_HEAD(&target->session_list);
Expand Down
8 changes: 4 additions & 4 deletions qla2x00t-32gbit/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4864,22 +4864,22 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
strlcpy(ha->model_desc,
strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
index = (ha->pdev->subsystem_device & 0xff);
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
strlcpy(ha->model_number,
strscpy(ha->model_number,
qla2x00_model_name[index * 2],
sizeof(ha->model_number));
strlcpy(ha->model_desc,
strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
strlcpy(ha->model_number, def,
strscpy(ha->model_number, def,
sizeof(ha->model_number));
}
}
Expand Down
20 changes: 10 additions & 10 deletions qla2x00t-32gbit/qla_mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
struct qla_hw_data *ha = vha->hw;

if (pci_is_pcie(ha->pdev))
strlcpy(str, "PCIe iSA", str_len);
strscpy(str, "PCIe iSA", str_len);
return str;
}

Expand Down Expand Up @@ -1860,21 +1860,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
phost_info = &preg_hsi->hsi;
memset(preg_hsi, 0, sizeof(struct register_host_info));
phost_info->os_type = OS_TYPE_LINUX;
strlcpy(phost_info->sysname, p_sysid->sysname,
strscpy(phost_info->sysname, p_sysid->sysname,
sizeof(phost_info->sysname));
strlcpy(phost_info->nodename, p_sysid->nodename,
strscpy(phost_info->nodename, p_sysid->nodename,
sizeof(phost_info->nodename));
if (!strcmp(phost_info->nodename, "(none)"))
ha->mr.host_info_resend = true;
strlcpy(phost_info->release, p_sysid->release,
strscpy(phost_info->release, p_sysid->release,
sizeof(phost_info->release));
strlcpy(phost_info->version, p_sysid->version,
strscpy(phost_info->version, p_sysid->version,
sizeof(phost_info->version));
strlcpy(phost_info->machine, p_sysid->machine,
strscpy(phost_info->machine, p_sysid->machine,
sizeof(phost_info->machine));
strlcpy(phost_info->domainname, p_sysid->domainname,
strscpy(phost_info->domainname, p_sysid->domainname,
sizeof(phost_info->domainname));
strlcpy(phost_info->hostdriver, QLA2XXX_VERSION,
strscpy(phost_info->hostdriver, QLA2XXX_VERSION,
sizeof(phost_info->hostdriver));
preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
ql_dbg(ql_dbg_init, vha, 0x0149,
Expand Down Expand Up @@ -1919,9 +1919,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
if (fx_type == FXDISC_GET_CONFIG_INFO) {
struct config_info_data *pinfo =
(struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
strlcpy(vha->hw->model_number, pinfo->model_num,
strscpy(vha->hw->model_number, pinfo->model_num,
ARRAY_SIZE(vha->hw->model_number));
strlcpy(vha->hw->model_desc, pinfo->model_description,
strscpy(vha->hw->model_desc, pinfo->model_description,
ARRAY_SIZE(vha->hw->model_desc));
memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
sizeof(vha->hw->mr.symbolic_name));
Expand Down
8 changes: 4 additions & 4 deletions qla2x00t/qla_gs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Model name. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
strlcpy(eiter->a.model, ha->model_number, sizeof(eiter->a.model));
strscpy(eiter->a.model, ha->model_number, sizeof(eiter->a.model));
alen = strlen(eiter->a.model);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
eiter->len = cpu_to_be16(4 + alen);
Expand All @@ -1365,7 +1365,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Model description. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
strlcpy(eiter->a.model_desc, ha->model_desc,
strscpy(eiter->a.model_desc, ha->model_desc,
sizeof(eiter->a.model_desc));
alen = strlen(eiter->a.model_desc);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
Expand All @@ -1378,7 +1378,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Hardware version. */
eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
strlcpy(eiter->a.hw_version, ha->adapter_id,
strscpy(eiter->a.hw_version, ha->adapter_id,
sizeof(eiter->a.hw_version));
alen = strlen(eiter->a.hw_version);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
Expand Down Expand Up @@ -1654,7 +1654,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
strlcpy(eiter->a.host_name, fc_host_system_hostname(vha->host),
strscpy(eiter->a.host_name, fc_host_system_hostname(vha->host),
sizeof(eiter->a.host_name));
alen = strlen(eiter->a.host_name);
alen += (alen & 3) ? (4 - (alen & 3)) : 4;
Expand Down
10 changes: 5 additions & 5 deletions qla2x00t/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -2162,7 +2162,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
!IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha);

if (memcmp(model, BINZERO, len) != 0) {
strncpy(ha->model_number, model, len);
memcpy(ha->model_number, model, len);
st = en = ha->model_number;
en += len - 1;
while (en > st) {
Expand All @@ -2175,22 +2175,22 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
strlcpy(ha->model_desc,
strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
index = (ha->pdev->subsystem_device & 0xff);
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
strlcpy(ha->model_number,
strscpy(ha->model_number,
qla2x00_model_name[index * 2],
sizeof(ha->model_number));
strlcpy(ha->model_desc,
strscpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc));
} else {
strlcpy(ha->model_number, def,
strscpy(ha->model_number, def,
sizeof(ha->model_number));
}
}
Expand Down
2 changes: 1 addition & 1 deletion qla2x00t/qla_nx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,7 +1599,7 @@ qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str, int str_len)
pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk);
ha->link_width = (lnk >> 4) & 0x3f;

strlcpy(str, "PCIe (", str_len);
strscpy(str, "PCIe (", str_len);
strncat(str, "2.5Gb/s ", str_len - (strlen(str)+1));
snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width);
strncat(str, lwstr, str_len - (strlen(str)+1));
Expand Down
2 changes: 1 addition & 1 deletion qla2x00t/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, int str_len)
};
uint16_t pci_bus;

strlcpy(str, "PCI", str_len);
strscpy(str, "PCI", str_len);
pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9;
if (pci_bus) {
strncat(str, "-X (", str_len - (strlen(str)+1));
Expand Down
23 changes: 23 additions & 0 deletions scst/include/backport.h
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,29 @@ static inline void *memdup_user_nul(const void __user *src, size_t len)
}
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) && \
(LINUX_VERSION_CODE >> 8 != KERNEL_VERSION(3, 16, 0) >> 8 || \
LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 60)) && \
(LINUX_VERSION_CODE >> 8 != KERNEL_VERSION(3, 18, 0) >> 8 || \
LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 64)) && \
(!defined(RHEL_RELEASE_CODE) || \
RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(7, 7))
/*
* See also commit 30035e45753b ("string: provide strscpy()") # v4.3, v3.16.60, v3.18.64.
*/
static inline ssize_t strscpy(char *dest, const char *src, size_t count)
{
size_t ret;

if (count == 0)
return -E2BIG;

ret = strlcpy(dest, src, count);

return ret >= count ? -E2BIG : ret;
}
#endif

/* <linux/sysfs.h> */

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) && \
Expand Down
6 changes: 3 additions & 3 deletions scst/src/dev_handlers/scst_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -3119,10 +3119,10 @@ static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
if (tgtt->get_scsi_transport_version != NULL)
ucmd->user_cmd.sess.scsi_transport_version =
tgtt->get_scsi_transport_version(tgt);
strlcpy(ucmd->user_cmd.sess.initiator_name,
strscpy(ucmd->user_cmd.sess.initiator_name,
tgt_dev->sess->initiator_name,
sizeof(ucmd->user_cmd.sess.initiator_name)-1);
strlcpy(ucmd->user_cmd.sess.target_name,
strscpy(ucmd->user_cmd.sess.target_name,
tgt_dev->sess->tgt->tgt_name,
sizeof(ucmd->user_cmd.sess.target_name)-1);

Expand Down Expand Up @@ -3369,7 +3369,7 @@ static int dev_user_register_dev(struct file *file,

scst_init_threads(&dev->udev_cmd_threads);

strlcpy(dev->name, dev_desc->name, sizeof(dev->name)-1);
strscpy(dev->name, dev_desc->name, sizeof(dev->name)-1);

scst_init_mem_lim(&dev->udev_mem_lim);

Expand Down
2 changes: 1 addition & 1 deletion scst/src/dev_handlers/scst_vdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -9366,7 +9366,7 @@ static ssize_t vdev_sysfs_bind_alua_state_store(struct kobject *kobj,

dev = container_of(kobj, struct scst_device, dev_kobj);
virt_dev = dev->dh_priv;
strlcpy(ch, buf, 16);
strscpy(ch, buf, 16);
res = kstrtoul(ch, 0, &bind_alua_state);
if (res < 0)
goto out;
Expand Down
2 changes: 1 addition & 1 deletion scst/src/scst_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ int debug_print_with_prefix(unsigned long trace_flag, const char *severity,

spin_lock_irqsave(&trace_buf_lock, flags);

strlcpy(trace_buf, severity, TRACE_BUF_SIZE);
strscpy(trace_buf, severity, TRACE_BUF_SIZE);
i = strlen(trace_buf);

if (trace_flag & TRACE_PID)
Expand Down
22 changes: 11 additions & 11 deletions scst/src/scst_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ void scst_event_queue(uint32_t event_code, const char *issuer_name,
TRACE_DBG("Scheduling event entry %p", e);

e->event.event_code = event_code;
strlcpy(e->event.issuer_name, issuer_name, sizeof(e->event.issuer_name));
strscpy(e->event.issuer_name, issuer_name, sizeof(e->event.issuer_name));

queue_work(scst_event_wq, &e->scst_event_queue_work);

Expand Down Expand Up @@ -317,9 +317,9 @@ int scst_event_queue_lun_not_found(const struct scst_cmd *cmd)
payload = (struct scst_event_lun_not_found_payload *)event->payload;

payload->lun = cmd->lun;
strlcpy(payload->initiator_name, cmd->sess->initiator_name,
strscpy(payload->initiator_name, cmd->sess->initiator_name,
sizeof(payload->initiator_name));
strlcpy(payload->target_name, cmd->tgt->tgt_name,
strscpy(payload->target_name, cmd->tgt->tgt_name,
sizeof(payload->target_name));

scst_event_queue(SCST_EVENT_LUN_NOT_FOUND,
Expand Down Expand Up @@ -358,9 +358,9 @@ int scst_event_queue_negative_luns_inquiry(const struct scst_tgt *tgt,
event->payload_len = sizeof(*payload);
payload = (struct scst_event_negative_luns_inquiry_payload *)event->payload;

strlcpy(payload->initiator_name, initiator_name,
strscpy(payload->initiator_name, initiator_name,
sizeof(payload->initiator_name));
strlcpy(payload->target_name, tgt->tgt_name,
strscpy(payload->target_name, tgt->tgt_name,
sizeof(payload->target_name));

scst_event_queue(SCST_EVENT_NEGATIVE_LUNS_INQUIRY,
Expand Down Expand Up @@ -399,7 +399,7 @@ int scst_event_queue_ext_blocking_done(struct scst_device *dev, void *data, int
event->payload_len = sizeof(*payload) + len;
payload = (struct scst_event_ext_blocking_done_payload *)event->payload;

strlcpy(payload->device_name, dev->virt_name, sizeof(payload->device_name));
strscpy(payload->device_name, dev->virt_name, sizeof(payload->device_name));
if (len > 0)
memcpy(payload->data, data, len);

Expand Down Expand Up @@ -442,13 +442,13 @@ int scst_event_queue_tm_fn_received(struct scst_mgmt_cmd *mcmd)
payload->fn = mcmd->fn;
payload->lun = mcmd->lun;
if (mcmd->mcmd_tgt_dev != NULL)
strlcpy(payload->device_name, mcmd->mcmd_tgt_dev->dev->virt_name,
strscpy(payload->device_name, mcmd->mcmd_tgt_dev->dev->virt_name,
sizeof(payload->device_name));
strlcpy(payload->initiator_name, mcmd->sess->initiator_name,
strscpy(payload->initiator_name, mcmd->sess->initiator_name,
sizeof(payload->initiator_name));
strlcpy(payload->target_name, mcmd->sess->tgt->tgt_name,
strscpy(payload->target_name, mcmd->sess->tgt->tgt_name,
sizeof(payload->target_name));
strlcpy(payload->session_sysfs_name, mcmd->sess->sess_name,
strscpy(payload->session_sysfs_name, mcmd->sess->sess_name,
sizeof(payload->session_sysfs_name));
if (mcmd->cmd_to_abort != NULL) {
payload->cmd_to_abort_tag = mcmd->cmd_to_abort->tag;
Expand Down Expand Up @@ -493,7 +493,7 @@ int scst_event_queue_reg_vdev(const char *dev_name)
event->payload_len = sizeof(*payload);
payload = (struct scst_event_reg_vdev_payload *)event->payload;

strlcpy(payload->device_name, dev_name,
strscpy(payload->device_name, dev_name,
sizeof(payload->device_name));

scst_event_queue(SCST_EVENT_REG_VIRT_DEV,
Expand Down
6 changes: 3 additions & 3 deletions scst/src/scst_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ char *scst_get_cmd_state_name(char *name, int len, unsigned int state)
{
if (state < ARRAY_SIZE(scst_cmd_state_name) &&
scst_cmd_state_name[state])
strlcpy(name, scst_cmd_state_name[state], len);
strscpy(name, scst_cmd_state_name[state], len);
else
snprintf(name, len, "%d", state);
return name;
Expand Down Expand Up @@ -703,7 +703,7 @@ static const char *const scst_tm_fn_name[] = {
char *scst_get_tm_fn_name(char *name, int len, unsigned int fn)
{
if (fn < ARRAY_SIZE(scst_tm_fn_name) && scst_tm_fn_name[fn])
strlcpy(name, scst_tm_fn_name[fn], len);
strscpy(name, scst_tm_fn_name[fn], len);
else
snprintf(name, len, "%d", fn);
return name;
Expand All @@ -723,7 +723,7 @@ char *scst_get_mcmd_state_name(char *name, int len, unsigned int state)
{
if (state < ARRAY_SIZE(scst_mcmd_state_name) &&
scst_mcmd_state_name[state])
strlcpy(name, scst_mcmd_state_name[state], len);
strscpy(name, scst_mcmd_state_name[state], len);
else
snprintf(name, len, "%d", state);
return name;
Expand Down
2 changes: 1 addition & 1 deletion scst/src/scst_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,7 @@ static int sgv_pool_init(struct sgv_pool *pool, const char *name,
name, sizeof(struct sgv_pool_obj), clustering_type,
single_alloc_pages, pool->max_caches, pool->max_cached_pages);

strlcpy(pool->name, name, sizeof(pool->name)-1);
strscpy(pool->name, name, sizeof(pool->name)-1);

pool->owner_mm = current->mm;

Expand Down
26 changes: 12 additions & 14 deletions scst/src/scst_tg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1739,9 +1739,8 @@ static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg,

res = 1;

if (strlcpy(payload->device_name, dev->virt_name,
sizeof(payload->device_name)) >=
sizeof(payload->device_name)) {
if (strscpy(payload->device_name, dev->virt_name,
sizeof(payload->device_name)) < 0) {
PRINT_ERROR("Device name %s too long", dev->virt_name);
goto out_too_long;
}
Expand All @@ -1752,19 +1751,18 @@ static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg,
if (osi[j].prev_state == osi[j].new_state)
continue;

if (strlcpy(descr->prev_state,
if (strscpy(descr->prev_state,
scst_alua_state_name(osi[j].prev_state),
sizeof(descr->prev_state)) >=
sizeof(descr->prev_state) ||
strlcpy(descr->new_state,
sizeof(descr->prev_state)) < 0 ||
strscpy(descr->new_state,
scst_alua_state_name(osi[j].new_state),
sizeof(descr->new_state)) >=
sizeof(descr->new_state) ||
strlcpy(descr->dg_name, dg->name, sizeof(descr->dg_name))
>= sizeof(descr->dg_name) ||
strlcpy(descr->tg_name, osi[j].tg->name,
sizeof(descr->tg_name)) >=
sizeof(descr->tg_name))
sizeof(descr->new_state)) < 0 ||
strscpy(descr->dg_name,
dg->name,
sizeof(descr->dg_name)) < 0 ||
strscpy(descr->tg_name,
osi[j].tg->name,
sizeof(descr->tg_name)) < 0)
goto out_too_long;

descr->group_id = osi[j].group_id;
Expand Down
Loading

0 comments on commit bc9ec6f

Please sign in to comment.