diff options
author | Tom Rix <trix@redhat.com> | 2020-09-02 23:26:50 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-09-17 14:55:28 +0300 |
commit | 61591cd38cdfc5f2102f95b91a102fd95d364f82 (patch) | |
tree | d32cf5c16acb496c9b5906b5d69b70f2905929d3 | |
parent | 6d1f49ae494dd133e13bbf74e8ca9b6508ed99ed (diff) | |
download | linux-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.c | 8 |
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: |