Messages in this thread | | | From | Nick Desaulniers <> | Date | Mon, 31 Aug 2020 10:47:42 -0700 | Subject | Re: [PATCH] soundwire: fix error handling |
| |
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>
Thanks for the patch!
> } > > msg_unlock: > -- > 2.18.1 >
-- Thanks, ~Nick Desaulniers
| |