2010-12-30 23:20:40

by Jesper Juhl

[permalink] [raw]
Subject: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

Hi,

We may leak the storage allocated to 'state' in
drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
This patch makes sure we free the allocated memory in the failure case.


Signed-off-by: Jesper Juhl <[email protected]>
---
ix2505v.c | 1 +
1 file changed, 1 insertion(+)

Compile tested only.

diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
index 55f2eba..fcb173d 100644
--- a/drivers/media/dvb/frontends/ix2505v.c
+++ b/drivers/media/dvb/frontends/ix2505v.c
@@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
ret = ix2505v_read_status_reg(state);

if (ret & 0x80) {
+ kfree(state);
deb_i2c("%s: No IX2505V found\n", __func__);
goto error;
}



--
Jesper Juhl <[email protected]> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.


2010-12-31 01:19:42

by Malcolm Priestley

[permalink] [raw]
Subject: Re: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

On Fri, 2010-12-31 at 00:11 +0100, Jesper Juhl wrote:
> Hi,
>
> We may leak the storage allocated to 'state' in
> drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
> This patch makes sure we free the allocated memory in the failure case.
>
>
> Signed-off-by: Jesper Juhl <[email protected]>
> ---
> ix2505v.c | 1 +
> 1 file changed, 1 insertion(+)
>
> Compile tested only.
>
> diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
> index 55f2eba..fcb173d 100644
> --- a/drivers/media/dvb/frontends/ix2505v.c
> +++ b/drivers/media/dvb/frontends/ix2505v.c
> @@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
> ret = ix2505v_read_status_reg(state);
>
> if (ret & 0x80) {
> + kfree(state);
> deb_i2c("%s: No IX2505V found\n", __func__);
> goto error;
> }
>
Memory is freed in...

error:
ix2505v_release(fe);
return NULL;

via...

static int ix2505v_release(struct dvb_frontend *fe)
{
struct ix2505v_state *state = fe->tuner_priv;

fe->tuner_priv = NULL;
kfree(state);

return 0;
}


Regards


Malcolm

2010-12-31 10:30:31

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: Re: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

Em 30-12-2010 21:11, Jesper Juhl escreveu:
> Hi,
>
> We may leak the storage allocated to 'state' in
> drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
> This patch makes sure we free the allocated memory in the failure case.
>
>
> Signed-off-by: Jesper Juhl <[email protected]>
> ---
> ix2505v.c | 1 +
> 1 file changed, 1 insertion(+)
>
> Compile tested only.
>
> diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
> index 55f2eba..fcb173d 100644
> --- a/drivers/media/dvb/frontends/ix2505v.c
> +++ b/drivers/media/dvb/frontends/ix2505v.c
> @@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
> ret = ix2505v_read_status_reg(state);
>
> if (ret & 0x80) {
> + kfree(state);

Instead of doing the free here, please move it to happen at the error: logic.
Currently, there's just one error condition, but having part of the release/kfree
logic here and there is not a good idea.

> deb_i2c("%s: No IX2505V found\n", __func__);
> goto error;
> }
>
>
>

2010-12-31 12:21:48

by Malcolm Priestley

[permalink] [raw]
Subject: Re: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

On Fri, 2010-12-31 at 08:30 -0200, Mauro Carvalho Chehab wrote:
> Em 30-12-2010 21:11, Jesper Juhl escreveu:
> > Hi,
> >
> > We may leak the storage allocated to 'state' in
> > drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
> > This patch makes sure we free the allocated memory in the failure case.
> >
> >
> > Signed-off-by: Jesper Juhl <[email protected]>
> > ---
> > ix2505v.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > Compile tested only.
> >
> > diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
> > index 55f2eba..fcb173d 100644
> > --- a/drivers/media/dvb/frontends/ix2505v.c
> > +++ b/drivers/media/dvb/frontends/ix2505v.c
> > @@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
> > ret = ix2505v_read_status_reg(state);
> >
> > if (ret & 0x80) {
> > + kfree(state);
>
> Instead of doing the free here, please move it to happen at the error: logic.
> Currently, there's just one error condition, but having part of the release/kfree
> logic here and there is not a good idea.
>
> > deb_i2c("%s: No IX2505V found\n", __func__);
> > goto error;
> > }

The state is already freed in ix2505v_release on error.

2010-12-31 15:00:46

by Jesper Juhl

[permalink] [raw]
Subject: Re: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

On Fri, 31 Dec 2010, Malcolm Priestley wrote:

> On Fri, 2010-12-31 at 00:11 +0100, Jesper Juhl wrote:
> > Hi,
> >
> > We may leak the storage allocated to 'state' in
> > drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
> > This patch makes sure we free the allocated memory in the failure case.
> >
> >
> > Signed-off-by: Jesper Juhl <[email protected]>
> > ---
> > ix2505v.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > Compile tested only.
> >
> > diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
> > index 55f2eba..fcb173d 100644
> > --- a/drivers/media/dvb/frontends/ix2505v.c
> > +++ b/drivers/media/dvb/frontends/ix2505v.c
> > @@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
> > ret = ix2505v_read_status_reg(state);
> >
> > if (ret & 0x80) {
> > + kfree(state);
> > deb_i2c("%s: No IX2505V found\n", __func__);
> > goto error;
> > }
> >
> Memory is freed in...
>
> error:
> ix2505v_release(fe);
> return NULL;
>
> via...
>
> static int ix2505v_release(struct dvb_frontend *fe)
> {
> struct ix2505v_state *state = fe->tuner_priv;
>
> fe->tuner_priv = NULL;
> kfree(state);
>
> return 0;
> }
>

Except that 'state' has not been assigned to fe->tuner_priv at this
point, so ix2505v_release() cannot free the memory that was just
allocated with kzalloc().


state is a local variable:
struct ix2505v_state *state = NULL;
...

we allocate memory and assign it to 'state' here:
state = kzalloc(sizeof(struct ix2505v_state), GFP_KERNEL);
if (NULL == state)
return NULL;

state->config = config;
state->i2c = i2c;

here 'state' is used, but not in a way that saves it anywhere:
if (state->config->tuner_write_only) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);

this function call involves 'state' but it does not save it anywhere
either:
ret = ix2505v_read_status_reg(state);

if (ret & 0x80) {
deb_i2c("%s: No IX2505V found\n", __func__);
so when we jump to error here 'state' still exists only as the local
variable, it has not been assigned to anything else.
goto error;
}
...
error:
there is no way this function call can free 'state' on this path since
it has not been assigned to fe->tuner_priv.
ix2505v_release(fe);
The local variable state goes out of scope here and leaks the memory it
points to:
return NULL;
}

Am I missing something?


--
Jesper Juhl <[email protected]> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.

2010-12-31 18:34:06

by Malcolm Priestley

[permalink] [raw]
Subject: Re: [PATVH] media, dvb, IX2505V: Remember to free allocated memory in failure path (ix2505v_attach()).

On Fri, 2010-12-31 at 15:51 +0100, Jesper Juhl wrote:
> On Fri, 31 Dec 2010, Malcolm Priestley wrote:
>
> > On Fri, 2010-12-31 at 00:11 +0100, Jesper Juhl wrote:
> > > Hi,
> > >
> > > We may leak the storage allocated to 'state' in
> > > drivers/media/dvb/frontends/ix2505v.c::ix2505v_attach() on error.
> > > This patch makes sure we free the allocated memory in the failure case.
> > >
> > >
> > > Signed-off-by: Jesper Juhl <[email protected]>
> > > ---
> > > ix2505v.c | 1 +
> > > 1 file changed, 1 insertion(+)
> > >
> > > Compile tested only.
> > >
> > > diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
> > > index 55f2eba..fcb173d 100644
> > > --- a/drivers/media/dvb/frontends/ix2505v.c
> > > +++ b/drivers/media/dvb/frontends/ix2505v.c
> > > @@ -293,6 +293,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
> > > ret = ix2505v_read_status_reg(state);
> > >
> > > if (ret & 0x80) {
> > > + kfree(state);
> > > deb_i2c("%s: No IX2505V found\n", __func__);
> > > goto error;
> > > }
> > >
> > Memory is freed in...
> >
> > error:
> > ix2505v_release(fe);
> > return NULL;
> >
> > via...
> >
> > static int ix2505v_release(struct dvb_frontend *fe)
> > {
> > struct ix2505v_state *state = fe->tuner_priv;
> >
> > fe->tuner_priv = NULL;
> > kfree(state);
> >
> > return 0;
> > }
> >
>
> Except that 'state' has not been assigned to fe->tuner_priv at this
> point, so ix2505v_release() cannot free the memory that was just
> allocated with kzalloc().
>
>
> state is a local variable:
> struct ix2505v_state *state = NULL;
> ...
>
> we allocate memory and assign it to 'state' here:
> state = kzalloc(sizeof(struct ix2505v_state), GFP_KERNEL);
> if (NULL == state)
> return NULL;
>
> state->config = config;
> state->i2c = i2c;
>
> here 'state' is used, but not in a way that saves it anywhere:
> if (state->config->tuner_write_only) {
> if (fe->ops.i2c_gate_ctrl)
> fe->ops.i2c_gate_ctrl(fe, 1);
>
> this function call involves 'state' but it does not save it anywhere
> either:
> ret = ix2505v_read_status_reg(state);
>
> if (ret & 0x80) {
> deb_i2c("%s: No IX2505V found\n", __func__);
> so when we jump to error here 'state' still exists only as the local
> variable, it has not been assigned to anything else.
> goto error;
> }
> ...
> error:
> there is no way this function call can free 'state' on this path since
> it has not been assigned to fe->tuner_priv.
> ix2505v_release(fe);
> The local variable state goes out of scope here and leaks the memory it
> points to:
> return NULL;
> }
>
> Am I missing something?

Oh, Sorry, I see it now.

Now there is two options.

Either;

1) Move fe->tuner_priv = state to below line 287, so it can be released
by ix2505v_release and fe->tuner_priv returned to NULL;

2) or not calling ix2505v_release changing line 314 to kfree(state).
fe->tuner_priv will remain NULL through out.

Currently, tuner_write_only is not implemented in the dvb-usb-lmedm04
driver, as sometimes it returned unpredictable results, and wrongly
failed to attach the tuner. Although, I will test it again.

Regards


Malcolm