@@ -41,10 +41,10 @@ long nf_get_id(const char *feature_name)
{
/* feature_name may be in vmalloc()ed memory, so make a copy */
char name_copy[32];
- size_t n;
+ ssize_t n;
- n = strlcpy(name_copy, feature_name, sizeof(name_copy));
- if (n >= sizeof(name_copy))
+ n = strscpy(name_copy, feature_name, sizeof(name_copy));
+ if (n == -E2BIG)
return 0;
return nf_get_id_phys(virt_to_phys(name_copy));
@@ -357,10 +357,10 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
* cipher name.
*/
if (!strncmp(cipher_name, "ecb(", 4)) {
- unsigned len;
+ ssize_t len;
- len = strlcpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
- if (len < 2 || len >= sizeof(ecb_name))
+ len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
+ if (len == -E2BIG || len < 2)
goto err_free_inst;
if (ecb_name[len - 1] != ')')
@@ -395,10 +395,10 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
* cipher name.
*/
if (!strncmp(cipher_name, "ecb(", 4)) {
- unsigned len;
+ ssize_t len;
- len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
- if (len < 2 || len >= sizeof(ctx->name))
+ len = strscpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
+ if (len == -E2BIG || len < 2)
goto err_free_inst;
if (ctx->name[len - 1] != ')')
@@ -42,12 +42,12 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
{
struct dma_buf *dmabuf;
char name[DMA_BUF_NAME_LEN];
- size_t ret = 0;
+ ssize_t ret = 0;
dmabuf = dentry->d_fsdata;
spin_lock(&dmabuf->name_lock);
if (dmabuf->name)
- ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
+ ret = strscpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
spin_unlock(&dmabuf->name_lock);
return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
@@ -107,7 +107,8 @@ struct max20730_debugfs_data {
static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- int ret, len;
+ int ret;
+ ssize_t len;
int *idxp = file->private_data;
int idx = *idxp;
struct max20730_debugfs_data *psu = to_psu(idxp, idx);
@@ -148,13 +149,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET1_TSTAT_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "125\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "125\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "32\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "32\n", DEBUG_FS_DATA_MAX);
break;
case MAX20730_DEBUGFS_INTERNAL_GAIN:
val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_RGAIN_MASK)
@@ -163,35 +164,35 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
if (data->id == max20734) {
/* AN6209 */
if (val == 0)
- len = strlcpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX);
} else if (data->id == max20730 || data->id == max20710) {
/* AN6042 or AN6140 */
if (val == 0)
- len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX);
} else if (data->id == max20743) {
/* AN6042 */
if (val == 0)
- len = strlcpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
} else {
- len = strlcpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX);
}
break;
case MAX20730_DEBUGFS_BOOT_VOLTAGE:
@@ -199,26 +200,26 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET1_VBOOT_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
break;
case MAX20730_DEBUGFS_OUT_V_RAMP_RATE:
val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_VRATE)
>> MAX20730_MFR_DEVSET2_VRATE_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "4\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "4\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "2\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "2\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "1\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
break;
case MAX20730_DEBUGFS_OC_PROTECT_MODE:
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
@@ -230,13 +231,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET2_SS_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX);
else if (val == 1)
- len = strlcpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX);
else if (val == 2)
- len = strlcpy(tbuf, "3\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "3\n", DEBUG_FS_DATA_MAX);
else
- len = strlcpy(tbuf, "6\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "6\n", DEBUG_FS_DATA_MAX);
break;
case MAX20730_DEBUGFS_IMAX:
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
@@ -287,9 +288,12 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
"%d.%d\n", ret / 10000, ret % 10000);
break;
default:
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ len = strscpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
}
+ if (len == -E2BIG)
+ return -E2BIG;
+
return simple_read_from_buffer(buf, count, ppos, tbuf, len);
}
@@ -158,8 +158,8 @@ ssize_t diag_ftp_cmd(const struct hmcdrv_ftp_cmdspec *ftp, size_t *fsize)
goto out;
}
- len = strlcpy(ldfpl->fident, ftp->fname, sizeof(ldfpl->fident));
- if (len >= HMCDRV_FTP_FIDENT_MAX) {
+ len = strscpy(ldfpl->fident, ftp->fname, sizeof(ldfpl->fident));
+ if (len == -E2BIG) {
len = -EINVAL;
goto out_free;
}
@@ -87,7 +87,7 @@ static int sclp_ftp_et7(const struct hmcdrv_ftp_cmdspec *ftp)
struct completion completion;
struct sclp_diag_sccb *sccb;
struct sclp_req *req;
- size_t len;
+ ssize_t len;
int rc;
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -114,9 +114,9 @@ static int sclp_ftp_et7(const struct hmcdrv_ftp_cmdspec *ftp)
sccb->evbuf.mdd.ftp.length = ftp->len;
sccb->evbuf.mdd.ftp.bufaddr = virt_to_phys(ftp->buf);
- len = strlcpy(sccb->evbuf.mdd.ftp.fident, ftp->fname,
+ len = strscpy(sccb->evbuf.mdd.ftp.fident, ftp->fname,
HMCDRV_FTP_FIDENT_MAX);
- if (len >= HMCDRV_FTP_FIDENT_MAX) {
+ if (len == -E2BIG) {
rc = -EINVAL;
goto out_free;
}
@@ -877,14 +877,16 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req;
struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp;
- int ret, len;
+ int ret;
+ ssize_t len;
zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
FC_SYMBOLIC_NAME_SIZE);
hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
- len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
+ len = strscpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
FC_SYMBOLIC_NAME_SIZE);
- rspn_req->rspn.fr_name_len = len;
+ if (len != -E2BIG)
+ rspn_req->rspn.fr_name_len = len;
sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));
sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp));
@@ -1325,16 +1325,11 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item,
/* +2 to allow for a trailing (stripped) '\n' and null-terminator */
unsigned char buf[INQUIRY_VENDOR_LEN + 2];
char *stripped = NULL;
- size_t len;
+ ssize_t len;
ssize_t ret;
- len = strlcpy(buf, page, sizeof(buf));
- if (len < sizeof(buf)) {
- /* Strip any newline added from userspace. */
- stripped = strstrip(buf);
- len = strlen(stripped);
- }
- if (len > INQUIRY_VENDOR_LEN) {
+ len = strscpy(buf, page, sizeof(buf));
+ if (len == -E2BIG) {
pr_err("Emulated T10 Vendor Identification exceeds"
" INQUIRY_VENDOR_LEN: " __stringify(INQUIRY_VENDOR_LEN)
"\n");
@@ -1381,16 +1376,11 @@ static ssize_t target_wwn_product_id_store(struct config_item *item,
/* +2 to allow for a trailing (stripped) '\n' and null-terminator */
unsigned char buf[INQUIRY_MODEL_LEN + 2];
char *stripped = NULL;
- size_t len;
+ ssize_t len;
ssize_t ret;
- len = strlcpy(buf, page, sizeof(buf));
- if (len < sizeof(buf)) {
- /* Strip any newline added from userspace. */
- stripped = strstrip(buf);
- len = strlen(stripped);
- }
- if (len > INQUIRY_MODEL_LEN) {
+ len = strscpy(buf, page, sizeof(buf));
+ if (len == -E2BIG) {
pr_err("Emulated T10 Vendor exceeds INQUIRY_MODEL_LEN: "
__stringify(INQUIRY_MODEL_LEN)
"\n");
@@ -1437,16 +1427,11 @@ static ssize_t target_wwn_revision_store(struct config_item *item,
/* +2 to allow for a trailing (stripped) '\n' and null-terminator */
unsigned char buf[INQUIRY_REVISION_LEN + 2];
char *stripped = NULL;
- size_t len;
+ ssize_t len;
ssize_t ret;
- len = strlcpy(buf, page, sizeof(buf));
- if (len < sizeof(buf)) {
- /* Strip any newline added from userspace. */
- stripped = strstrip(buf);
- len = strlen(stripped);
- }
- if (len > INQUIRY_REVISION_LEN) {
+ len = strscpy(buf, page, sizeof(buf));
+ if (len == -E2BIG) {
pr_err("Emulated T10 Revision exceeds INQUIRY_REVISION_LEN: "
__stringify(INQUIRY_REVISION_LEN)
"\n");
@@ -2031,9 +2031,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
ssize_t len = sizeof(user_kdgkb->kb_string);
spin_lock_irqsave(&func_buf_lock, flags);
- len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
+ len = strscpy(kbs->kb_string, func_table[i] ? : "", len);
spin_unlock_irqrestore(&func_buf_lock, flags);
+ if (len == -E2BIG) {
+ ret = -E2BIG;
+ goto reterr;
+ }
+
ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
len + 1) ? -EFAULT : 0;
@@ -1135,11 +1135,11 @@ F_MIDI_OPT(out_ports, true, MAX_PORTS);
static ssize_t f_midi_opts_id_show(struct config_item *item, char *page)
{
struct f_midi_opts *opts = to_f_midi_opts(item);
- int result;
+ ssize_t result;
mutex_lock(&opts->lock);
if (opts->id) {
- result = strlcpy(page, opts->id, PAGE_SIZE);
+ result = strscpy(page, opts->id, PAGE_SIZE);
} else {
page[0] = 0;
result = 0;
@@ -1209,15 +1209,15 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
char *page)
{
struct f_printer_opts *opts = to_f_printer_opts(item);
- int result = 0;
+ ssize_t result = 0;
mutex_lock(&opts->lock);
if (!opts->pnp_string)
goto unlock;
- result = strlcpy(page, opts->pnp_string, PAGE_SIZE);
- if (result >= PAGE_SIZE) {
- result = PAGE_SIZE;
+ result = strscpy(page, opts->pnp_string, PAGE_SIZE);
+ if (result == -E2BIG) {
+ goto unlock;
} else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) {
page[result++] = '\n';
page[result] = '\0';
@@ -169,15 +169,15 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf)
static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
size_t count)
{
- int len;
+ ssize_t len;
char busid[BUSID_SIZE];
if (count < 5)
return -EINVAL;
/* busid needs to include \0 termination */
- len = strlcpy(busid, buf + 4, BUSID_SIZE);
- if (sizeof(busid) <= len)
+ len = strscpy(busid, buf + 4, BUSID_SIZE);
+ if (len == -E2BIG)
return -EINVAL;
if (!strncmp(buf, "add ", 4)) {
@@ -111,7 +111,7 @@ static unsigned long wdt_status;
static int wdt_start(struct watchdog_device *dev)
{
char *ebc_cmd;
- size_t len;
+ ssize_t len;
int ret;
unsigned int func;
@@ -126,7 +126,9 @@ static int wdt_start(struct watchdog_device *dev)
clear_bit(DIAG_WDOG_BUSY, &wdt_status);
return -ENOMEM;
}
- len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
+ len = strscpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
+ if (len == -E2BIG)
+ return -E2BIG;
ASCEBC(ebc_cmd, MAX_CMDLEN);
EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
@@ -163,7 +165,7 @@ static int wdt_stop(struct watchdog_device *dev)
static int wdt_ping(struct watchdog_device *dev)
{
char *ebc_cmd;
- size_t len;
+ ssize_t len;
int ret;
unsigned int func;
@@ -173,7 +175,9 @@ static int wdt_ping(struct watchdog_device *dev)
ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
if (!ebc_cmd)
return -ENOMEM;
- len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
+ len = strscpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
+ if (len == -E2BIG)
+ return -E2BIG;
ASCEBC(ebc_cmd, MAX_CMDLEN);
EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
@@ -42,9 +42,9 @@ static bool kernfs_lockdep(struct kernfs_node *kn)
static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
{
if (!kn)
- return strlcpy(buf, "(null)", buflen);
+ return strscpy(buf, "(null)", buflen);
- return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
+ return strscpy(buf, kn->parent ? kn->name : "/", buflen);
}
/* kernfs_node_depth - compute depth from @from to @to */
@@ -125,17 +125,18 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
{
struct kernfs_node *kn, *common;
const char parent_str[] = "/..";
- size_t depth_from, depth_to, len = 0;
+ size_t depth_from, depth_to;
+ ssize_t len = 0;
int i, j;
if (!kn_to)
- return strlcpy(buf, "(null)", buflen);
+ return strscpy(buf, "(null)", buflen);
if (!kn_from)
kn_from = kernfs_root(kn_to)->kn;
if (kn_from == kn_to)
- return strlcpy(buf, "/", buflen);
+ return strscpy(buf, "/", buflen);
if (!buf)
return -EINVAL;
@@ -150,16 +151,16 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
buf[0] = '\0';
for (i = 0; i < depth_from; i++)
- len += strlcpy(buf + len, parent_str,
+ len += strscpy(buf + len, parent_str,
len < buflen ? buflen - len : 0);
/* Calculate how many bytes we need for the rest */
for (i = depth_to - 1; i >= 0; i--) {
for (kn = kn_to, j = 0; j < i; j++)
kn = kn->parent;
- len += strlcpy(buf + len, "/",
+ len += strscpy(buf + len, "/",
len < buflen ? buflen - len : 0);
- len += strlcpy(buf + len, kn->name,
+ len += strscpy(buf + len, kn->name,
len < buflen ? buflen - len : 0);
}
@@ -173,8 +174,8 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
* @buflen: size of @buf
*
* Copies the name of @kn into @buf of @buflen bytes. The behavior is
- * similar to strlcpy(). It returns the length of @kn's name and if @buf
- * isn't long enough, it's filled upto @buflen-1 and nul terminated.
+ * similar to strscpy(). It returns the length of @kn's name and if @buf
+ * isn't long enough or @buflen is 0, it returns -E2BIG.
*
* Fills buffer with "(null)" if @kn is NULL.
*
@@ -859,7 +860,7 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
const unsigned char *path,
const void *ns)
{
- size_t len;
+ ssize_t len;
char *p, *name;
lockdep_assert_held(&kernfs_mutex);
@@ -867,9 +868,9 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
/* grab kernfs_rename_lock to piggy back on kernfs_pr_cont_buf */
spin_lock_irq(&kernfs_rename_lock);
- len = strlcpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
+ len = strscpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
- if (len >= sizeof(kernfs_pr_cont_buf)) {
+ if (len == -E2BIG) {
spin_unlock_irq(&kernfs_rename_lock);
return NULL;
}
@@ -2268,7 +2268,7 @@ int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
ret = cgroup_path_ns_locked(cgrp, buf, buflen, &init_cgroup_ns);
} else {
/* if no hierarchy exists, everyone is in "/" */
- ret = strlcpy(buf, "/", buflen);
+ ret = strscpy(buf, "/", buflen);
}
spin_unlock_irq(&css_set_lock);
@@ -2777,6 +2777,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
Elf_Sym *dst;
char *s;
Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
+ ssize_t len;
/* Set up to point into init section. */
mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off;
@@ -2804,8 +2805,9 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
mod->kallsyms->typetab[i];
dst[ndst] = src[i];
dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
- s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
+ len = strscpy(s, &mod->kallsyms->strtab[src[i].st_name],
KSYM_NAME_LEN) + 1;
+ s += (len != -E2BIG) ? len : 0;
}
}
mod->core_kallsyms.num_symtab = ndst;
@@ -154,12 +154,11 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
u8 *dst = get_loc_data(dest, base);
void __user *src = (void __force __user *) addr;
- if (unlikely(!maxlen))
- return -ENOMEM;
-
- if (addr == FETCH_TOKEN_COMM)
- ret = strlcpy(dst, current->comm, maxlen);
- else
+ if (addr == FETCH_TOKEN_COMM) {
+ ret = strscpy(dst, current->comm, maxlen);
+ if (ret == -E2BIG)
+ return -ENOMEM;
+ } else
ret = strncpy_from_user(dst, src, maxlen);
if (ret >= 0) {
if (ret == maxlen)
@@ -251,11 +251,11 @@ static int kobj_usermode_filter(struct kobject *kobj)
static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
{
- int len;
+ ssize_t len;
- len = strlcpy(&env->buf[env->buflen], subsystem,
+ len = strscpy(&env->buf[env->buflen], subsystem,
sizeof(env->buf) - env->buflen);
- if (len >= (sizeof(env->buf) - env->buflen)) {
+ if (len == -E2BIG) {
WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
return -ENOMEM;
}
@@ -9200,10 +9200,10 @@ EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
void devlink_param_value_str_fill(union devlink_param_value *dst_val,
const char *src)
{
- size_t len;
+ ssize_t len;
- len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
- WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
+ len = strscpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
+ WARN_ON(len == -E2BIG);
}
EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
@@ -282,7 +282,7 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
{
- clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
+ clnt->cl_nodelen = strscpy(clnt->cl_nodename,
nodename, sizeof(clnt->cl_nodename));
}
@@ -422,6 +422,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
nodename = utsname()->nodename;
/* save the nodename */
rpc_clnt_set_nodename(clnt, nodename);
+ if (clnt->cl_nodelen == -E2BIG) {
+ err = -ENOMEM;
+ goto out_no_path;
+ }
err = rpc_client_register(clnt, args->authflavor, args->client_name);
if (err)
@@ -760,8 +760,14 @@ static int __init ima_init_arch_policy(void)
for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
char rule[255];
int result;
+ ssize_t len;
- result = strlcpy(rule, *rules, sizeof(rule));
+ len = strscpy(rule, *rules, sizeof(rule));
+ if (len == -E2BIG) {
+ pr_warn("Internal copy of architecture policy rule '%s' "
+ "failed. Skipping.\n", *rules);
+ continue;
+ }
INIT_LIST_HEAD(&arch_policy_entry[i].list);
result = ima_parse_rule(rule, &arch_policy_entry[i]);
@@ -494,7 +494,7 @@ static void usb_audio_make_longname(struct usb_device *dev,
struct snd_card *card = chip->card;
const struct usb_audio_device_name *preset;
const char *s = NULL;
- int len;
+ ssize_t len;
preset = lookup_device_name(chip->usb_id);
@@ -511,7 +511,7 @@ static void usb_audio_make_longname(struct usb_device *dev,
else if (quirk && quirk->vendor_name)
s = quirk->vendor_name;
if (s && *s) {
- len = strlcpy(card->longname, s, sizeof(card->longname));
+ len = strscpy(card->longname, s, sizeof(card->longname));
} else {
/* retrieve the vendor and device strings as longname */
if (dev->descriptor.iManufacturer)
The strlcpy() reads the entire source buffer first, it is dangerous if the source buffer lenght is unbounded or possibility non NULL-terminated. It can lead to linear read overflows, crashes, etc... As recommended in the deprecated interfaces [1], it should be replaced by strscpy. This commit replaces all calls to strlcpy that handle the return values by the corresponding strscpy calls with new handling of the return values (as it is quite different between the two functions). [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy Signed-off-by: Romain Perier <romain.perier@gmail.com> --- arch/m68k/emu/natfeat.c | 6 +-- crypto/lrw.c | 6 +-- crypto/xts.c | 6 +-- drivers/dma-buf/dma-buf.c | 4 +- drivers/hwmon/pmbus/max20730.c | 66 +++++++++++++------------ drivers/s390/char/diag_ftp.c | 4 +- drivers/s390/char/sclp_ftp.c | 6 +-- drivers/s390/scsi/zfcp_fc.c | 8 +-- drivers/target/target_core_configfs.c | 33 ++++--------- drivers/tty/vt/keyboard.c | 7 ++- drivers/usb/gadget/function/f_midi.c | 4 +- drivers/usb/gadget/function/f_printer.c | 8 +-- drivers/usb/usbip/stub_main.c | 6 +-- drivers/watchdog/diag288_wdt.c | 12 +++-- fs/kernfs/dir.c | 27 +++++----- kernel/cgroup/cgroup.c | 2 +- kernel/module.c | 4 +- kernel/trace/trace_uprobe.c | 11 ++--- lib/kobject_uevent.c | 6 +-- net/core/devlink.c | 6 +-- net/sunrpc/clnt.c | 6 ++- security/integrity/ima/ima_policy.c | 8 ++- sound/usb/card.c | 4 +- 23 files changed, 131 insertions(+), 119 deletions(-)