On Fri, 30 Nov 2018 16:55:42 +0100
Alexandre Ratchov <a...@caoua.org> wrote:

> On Fri, Nov 30, 2018 at 01:49:56PM +0100, Benjamin Baier wrote:
> > Hi
> > 
> > There is a leak of *arg in 
> > dev/usb/if_athn_usb.c:athn_usb_newauth() line 1263
> > since Rev. 1.49
> > Because athn_usb_do_async() memcpy's the argument anyway.
> > 
> > Found with llvm/scan-build.
> > 
> > Instead of adding free(arg) I opted to make this function
> > more like the other ones which call athn_usb_do_async.
> >   
> 
> Hi,
> 
> AFAICS, athn_usb_do_async() will schedule a call to
> athn_usb_newauth_cb(), which will use arg after the functin has
> returned. The arg memory location must stay valid after return from
> athn_usb_newauth(). So we can neither use free() nor a local variable.

athn_usb_do_async() takes care of that by memcpy-ing arg to cmd->data
before calling usb_add_task().

other calls to athn_usb_do_async() do use local variables.
if_athn_usb.c:1032:athn_usb_do_async(usc, athn_usb_newstate_cb, &cmd, 
sizeof(cmd));
if_athn_usb.c:1317:athn_usb_do_async(usc, athn_usb_ampdu_tx_start_cb, &cmd, 
sizeof(cmd));
if_athn_usb.c:1641:athn_usb_do_async(usc, athn_usb_set_key_cb, &cmd, 
sizeof(cmd));
if_athn_usb.c:1673:athn_usb_do_async(usc, athn_usb_delete_key_cb, &cmd, 
sizeof(cmd));

> The athn_usb_newauth_cb() callback calls free(), so there's no memory
> leak unless the callback is cancelled. I don't know it can be
> cancelled, I see no code doing so.
> 
> > Only compile tested... looking for tests.
> > 
> > Greetings Ben
> > 
> > Index: if_athn_usb.c
> > ===================================================================
> > RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
> > retrieving revision 1.51
> > diff -u -p -r1.51 if_athn_usb.c
> > --- if_athn_usb.c   6 Sep 2018 11:50:54 -0000       1.51
> > +++ if_athn_usb.c   29 Nov 2018 18:33:40 -0000
> > @@ -1231,7 +1231,7 @@ athn_usb_newauth(struct ieee80211com *ic
> >     struct ifnet *ifp = &ic->ic_if;
> >     struct athn_node *an = (struct athn_node *)ni;
> >     int nsta;
> > -   struct athn_usb_newauth_cb_arg *arg;
> > +   struct athn_usb_newauth_cb_arg arg;
> >  
> >     if (ic->ic_opmode != IEEE80211_M_HOSTAP)
> >             return 0;
> > @@ -1254,12 +1254,9 @@ athn_usb_newauth(struct ieee80211com *ic
> >      * In a process context, try to add this node to the
> >      * firmware table and confirm the AUTH request.
> >      */
> > -   arg = malloc(sizeof(*arg), M_DEVBUF, M_NOWAIT);
> > -   if (arg == NULL)
> > -           return ENOMEM;
> > -   arg->ni = ieee80211_ref_node(ni);
> > -   arg->seq = seq;
> > -   athn_usb_do_async(usc, athn_usb_newauth_cb, arg, sizeof(*arg));
> > +   arg.ni = ieee80211_ref_node(ni);
> > +   arg.seq = seq;
> > +   athn_usb_do_async(usc, athn_usb_newauth_cb, &arg, sizeof(arg));
> >     return EBUSY;
> >  #else
> >     return 0;
> >   
> 

Reply via email to