| From f3beb7b50f5a00fd391c2346b70a63d450156306 Mon Sep 17 00:00:00 2001 |
| From: Silvio Cesare <silvio.cesare@gmail.com> |
| Date: Sat, 12 Jan 2019 16:28:43 +0100 |
| Subject: ASoC: dapm: change snprintf to scnprintf for possible overflow |
| |
| [ Upstream commit e581e151e965bf1f2815dd94620b638fec4d0a7e ] |
| |
| Change snprintf to scnprintf. There are generally two cases where using |
| snprintf causes problems. |
| |
| 1) Uses of size += snprintf(buf, SIZE - size, fmt, ...) |
| In this case, if snprintf would have written more characters than what the |
| buffer size (SIZE) is, then size will end up larger than SIZE. In later |
| uses of snprintf, SIZE - size will result in a negative number, leading |
| to problems. Note that size might already be too large by using |
| size = snprintf before the code reaches a case of size += snprintf. |
| |
| 2) If size is ultimately used as a length parameter for a copy back to user |
| space, then it will potentially allow for a buffer overflow and information |
| disclosure when size is greater than SIZE. When the size is used to index |
| the buffer directly, we can have memory corruption. This also means when |
| size = snprintf... is used, it may also cause problems since size may become |
| large. Copying to userspace is mitigated by the HARDENED_USERCOPY kernel |
| configuration. |
| |
| The solution to these issues is to use scnprintf which returns the number of |
| characters actually written to the buffer, so the size variable will never |
| exceed SIZE. |
| |
| Signed-off-by: Silvio Cesare <silvio.cesare@gmail.com> |
| Cc: Liam Girdwood <lgirdwood@gmail.com> |
| Cc: Mark Brown <broonie@kernel.org> |
| Cc: Dan Carpenter <dan.carpenter@oracle.com> |
| Cc: Kees Cook <keescook@chromium.org> |
| Cc: Will Deacon <will.deacon@arm.com> |
| Cc: Greg KH <greg@kroah.com> |
| Signed-off-by: Willy Tarreau <w@1wt.eu> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/soc/soc-dapm.c | 10 +++++----- |
| 1 file changed, 5 insertions(+), 5 deletions(-) |
| |
| diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c |
| index 461d951917c05..6537069452226 100644 |
| --- a/sound/soc/soc-dapm.c |
| +++ b/sound/soc/soc-dapm.c |
| @@ -2028,19 +2028,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file, |
| out = is_connected_output_ep(w, NULL, NULL); |
| } |
| |
| - ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", |
| + ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", |
| w->name, w->power ? "On" : "Off", |
| w->force ? " (forced)" : "", in, out); |
| |
| if (w->reg >= 0) |
| - ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| + ret += scnprintf(buf + ret, PAGE_SIZE - ret, |
| " - R%d(0x%x) mask 0x%x", |
| w->reg, w->reg, w->mask << w->shift); |
| |
| - ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
| + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
| |
| if (w->sname) |
| - ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n", |
| + ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n", |
| w->sname, |
| w->active ? "active" : "inactive"); |
| |
| @@ -2053,7 +2053,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, |
| if (!p->connect) |
| continue; |
| |
| - ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| + ret += scnprintf(buf + ret, PAGE_SIZE - ret, |
| " %s \"%s\" \"%s\"\n", |
| (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out", |
| p->name ? p->name : "static", |
| -- |
| 2.19.1 |
| |