Messages in this thread | | | Subject | Re: [PATCH] soundwire: fix error handling | From | Pierre-Louis Bossart <> | Date | Mon, 31 Aug 2020 17:45:47 -0500 |
| |
On 8/31/20 12:47 PM, Nick Desaulniers wrote: > On Sat, Aug 29, 2020 at 8:35 AM <trix@redhat.com> wrote: >> >> From: Tom Rix <trix@redhat.com> >> >> 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> >> --- >> drivers/soundwire/stream.c | 8 +++++--- >> 1 file changed, 5 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c >> index 37290a799023..6e36deb505b1 100644 >> --- a/drivers/soundwire/stream.c >> +++ b/drivers/soundwire/stream.c >> @@ -717,6 +717,7 @@ static int sdw_bank_switch(struct sdw_bus *bus, int m_rt_count) >> kfree(wbuf); >> error_1: >> kfree(wr_msg); >> + bus->defer_msg.msg = NULL; > > This fix looks correct to me because L668 sets `bus->defer_msg.msg = > wr_msg;`, but on error L719 frees `wr_msg`, so now > `bus->defer_msg.msg` is a dangling pointer. > >> return ret; >> } >> >> @@ -840,9 +841,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); >> + } > > I'd prefer a conditional check for each, but sdw_ml_sync_bank_switch() > has this same pattern, so it looks like the lifetime of these two > match. > > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Also looks good to me.
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
| |