summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiba Prasad <sibap@codeaurora.org>2017-09-13 20:43:57 +0530
committerSiba Prasad <sibap@codeaurora.org>2017-10-13 11:33:27 +0530
commitbc520b9e3e005be1c5925e058f571a76658bbcd8 (patch)
tree4e9ab368a139e80337f596ed08a0ed0564851ee3
parent14f6bfeeebb97c02cbf0c43818f7998e3bdb3cae (diff)
mmc: core: Prevent accessing user space buffer directly
In mmc_wr_pack_stats_read(), userspace buffer is directly accessed which is violating PAN (Privilege Access Never). So to prevent this, data which needs to be copied to user buffer is gathered into a local buffer and at the end, this local buffer contents are copied back to buffer supplied from user space using copy_to_user(). Change-Id: Id772613fe54c47d64906c18d3d0249eee2f6ac26 Signed-off-by: Siba Prasad <sibap@codeaurora.org>
-rw-r--r--drivers/mmc/core/debugfs.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 72bfdd835178..26fa4a4d96b0 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -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);