Merge "mmc: core: Prevent accessing user space buffer directly"

This commit is contained in:
Linux Build Service Account 2017-10-23 05:47:58 -07:00 committed by Gerrit - the friendly Code Review server
commit 82e598b10a

View file

@ -591,9 +591,10 @@ static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf,
{
struct mmc_card *card = filp->private_data;
struct mmc_wr_pack_stats *pack_stats;
int i;
int i, ret = 0;
int max_num_of_packed_reqs = 0;
char *temp_buf;
char *temp_buf, *temp_ubuf;
size_t tubuf_cnt = 0;
if (!card)
return cnt;
@ -619,15 +620,24 @@ static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf,
max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
temp_buf = kmalloc(TEMP_BUF_SIZE, GFP_KERNEL);
if (cnt <= (strlen_user(ubuf) + 1))
goto exit;
temp_buf = kzalloc(TEMP_BUF_SIZE, GFP_KERNEL);
if (!temp_buf)
goto exit;
tubuf_cnt = cnt - strlen_user(ubuf) - 1;
temp_ubuf = kzalloc(tubuf_cnt, GFP_KERNEL);
if (!temp_ubuf)
goto cleanup;
spin_lock(&pack_stats->lock);
snprintf(temp_buf, TEMP_BUF_SIZE, "%s: write packing statistics:\n",
mmc_hostname(card->host));
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
if (pack_stats->packing_events[i]) {
@ -635,63 +645,63 @@ static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf,
"%s: Packed %d reqs - %d times\n",
mmc_hostname(card->host), i,
pack_stats->packing_events[i]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
}
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: stopped packing due to the following reasons:\n",
mmc_hostname(card->host));
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
if (pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: exceed max num of segments\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[EXCEEDS_SECTORS]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: exceed max num of sectors\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EXCEEDS_SECTORS]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[WRONG_DATA_DIR]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: wrong data direction\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[WRONG_DATA_DIR]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: flush or discard\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[EMPTY_QUEUE]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: empty queue\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EMPTY_QUEUE]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[REL_WRITE]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: rel write\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[REL_WRITE]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[THRESHOLD]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: Threshold\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[THRESHOLD]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]) {
@ -699,25 +709,36 @@ static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf,
"%s: %d times: Large sector alignment\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[RANDOM]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: random request\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[RANDOM]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[FUA]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: fua request\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[FUA]);
strlcat(ubuf, temp_buf, cnt);
strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (strlen_user(ubuf) < cnt - strlen(temp_ubuf))
ret = copy_to_user((ubuf + strlen_user(ubuf)),
temp_ubuf, tubuf_cnt);
else
ret = -EFAULT;
if (ret)
pr_err("%s: %s: Copy to userspace failed: %s\n",
mmc_hostname(card->host), __func__, ubuf);
spin_unlock(&pack_stats->lock);
kfree(temp_ubuf);
cleanup:
kfree(temp_buf);
pr_info("%s", ubuf);