summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rix <trix@redhat.com>2020-09-02 23:26:50 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-09-17 14:55:28 +0300
commit61591cd38cdfc5f2102f95b91a102fd95d364f82 (patch)
treed32cf5c16acb496c9b5906b5d69b70f2905929d3
parent6d1f49ae494dd133e13bbf74e8ca9b6508ed99ed (diff)
downloadlinux-61591cd38cdfc5f2102f95b91a102fd95d364f82.tar.xz
soundwire: fix double free of dangling pointer
[ Upstream commit 3fbbf2148a406b3e350fe91e6fdd78eb42ecad24 ] clang static analysis flags this problem stream.c:844:9: warning: Use of memory after it is freed kfree(bus->defer_msg.msg->buf); ^~~~~~~~~~~~~~~~~~~~~~~ This happens in an error handler cleaning up memory allocated for elements in a list. list_for_each_entry(m_rt, &stream->master_list, stream_node) { bus = m_rt->bus; kfree(bus->defer_msg.msg->buf); kfree(bus->defer_msg.msg); } And is triggered when the call to sdw_bank_switch() fails. There are a two problems. First, when sdw_bank_switch() fails, though it frees memory it does not clear bus's reference 'defer_msg.msg' to that memory. The second problem is the freeing msg->buf. In some cases msg will be NULL so this will dereference a null pointer. Need to check before freeing. Fixes: 99b8a5d608a6 ("soundwire: Add bank switch routine") Signed-off-by: Tom Rix <trix@redhat.com> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20200902202650.14189-1-trix@redhat.com Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/soundwire/stream.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index a9a72574b34a..684761e86d4f 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -716,6 +716,7 @@ error:
kfree(wbuf);
error_1:
kfree(wr_msg);
+ bus->defer_msg.msg = NULL;
return ret;
}
@@ -839,9 +840,10 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
error:
list_for_each_entry(m_rt, &stream->master_list, stream_node) {
bus = m_rt->bus;
-
- kfree(bus->defer_msg.msg->buf);
- kfree(bus->defer_msg.msg);
+ if (bus->defer_msg.msg) {
+ kfree(bus->defer_msg.msg->buf);
+ kfree(bus->defer_msg.msg);
+ }
}
msg_unlock: