Merge "mmc: core: Prevent accessing user space buffer directly"
This commit is contained in:
commit
82e598b10a
1 changed files with 37 additions and 16 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue