diff mbox

sound: Don't assume i2c device probing always succeeds

Message ID s5h4oqkxy3e.wl%tiwai@suse.de (mailing list archive)
State Not Applicable
Headers show

Commit Message

Takashi Iwai Sept. 30, 2009, 3:15 p.m. UTC
At Wed, 30 Sep 2009 17:00:06 +0200,
Jean Delvare wrote:
> 
> Hi Takashi,
> 
> Thanks for the swift reply.
> 
> On Wed, 30 Sep 2009 16:13:49 +0200, Takashi Iwai wrote:
> > At Wed, 30 Sep 2009 15:25:42 +0200,
> > Jean Delvare wrote:
> > > 
> > > If i2c device probing fails, then there is no driver to dereference
> > > after calling i2c_new_device(). Stop assuming that probing will always
> > > succeed, to avoid NULL pointer dereferences. We have an easier access
> > > to the driver anyway.
> > > 
> > > Reported-by: Tim Shepard <shep@alum.mit.edu>
> > > Signed-off-by: Jean Delvare <khali@linux-fr.org>
> > > Cc: Johannes Berg <johannes@sipsolutions.net>
> > > ---
> > > The code is similar to the one in therm_adt746x, for which Tim reported
> > > a real-world oops, so it should be fixed ASAP.
> > 
> > Jean, thanks for the patch.
> > 
> > I'm just wondering whether the additional NULL check of client->driver
> > would be enough?  If yes, sound/aoa/onyx.c has it, at least, and we
> > can add the similar checks to the rest, too.
> 
> The NULL check of client->driver, if followed by a call to
> i2c_unregister_device(), would indeed be enough. But unlike the onyx
> driver which we know we sometimes load erroneously, the other drivers
> should never fail. I am reluctant to add code to handle error cases
> which are not supposed to happen, which is why I prefer my proposed
> fix: it does not add code.
> 
> That being said, I will be happy with any solution that fixes the
> problem, so if you prefer client->driver NULL checks, I can send a
> patch doing this.

Yes, indeed I prefer NULL check because the user can know the error
at the right place.  I share your concern about the code addition,
though :)

I already made a patch below, but it's totally untested.
It'd be helpful if someone can do review and build-test it.


thanks,

Takashi

---

Comments

Jean Delvare Sept. 30, 2009, 4:55 p.m. UTC | #1
On Wed, 30 Sep 2009 17:15:49 +0200, Takashi Iwai wrote:
> Yes, indeed I prefer NULL check because the user can know the error
> at the right place.  I share your concern about the code addition,
> though :)
> 
> I already made a patch below, but it's totally untested.
> It'd be helpful if someone can do review and build-test it.
> 
> 
> thanks,
> 
> Takashi
> 
> ---
> diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
> index f0ebc97..0f810c8 100644
> --- a/sound/aoa/codecs/tas.c
> +++ b/sound/aoa/codecs/tas.c
> @@ -897,6 +897,10 @@ static int tas_create(struct i2c_adapter *adapter,
>  	client = i2c_new_device(adapter, &info);
>  	if (!client)
>  		return -ENODEV;
> +	if (!client->driver) {
> +		i2c_unregister_device(client);
> +		return -ENODEV;
> +	}
>  
>  	/*
>  	 * Let i2c-core delete that device on driver removal.
> diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
> index 835fa19..473c5a6 100644
> --- a/sound/ppc/keywest.c
> +++ b/sound/ppc/keywest.c
> @@ -59,6 +59,13 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
>  	strlcpy(info.type, "keywest", I2C_NAME_SIZE);
>  	info.addr = keywest_ctx->addr;
>  	keywest_ctx->client = i2c_new_device(adapter, &info);
> +	if (!keywest_ctx->client)
> +		return -ENODEV;
> +	if (!keywest_ctx->client->driver) {
> +		i2c_unregister_device(keywest_ctx->client);
> +		keywest_ctx->client = NULL;
> +		return -ENODEV;
> +	}
>  	
>  	/*
>  	 * Let i2c-core delete that device on driver removal.

This looks good to me. Please add the following comment before the
client->driver check in both drivers:

	/*
	 * We know the driver is already loaded, so the device should be
	 * already bound. If not it means binding failed, and then there
	 * is no point in keeping the device instantiated.
	 */

Otherwise it's a little difficult to understand why the check is there.
Takashi Iwai Oct. 1, 2009, 6:52 a.m. UTC | #2
At Wed, 30 Sep 2009 18:55:05 +0200,
Jean Delvare wrote:
> 
> On Wed, 30 Sep 2009 17:15:49 +0200, Takashi Iwai wrote:
> > Yes, indeed I prefer NULL check because the user can know the error
> > at the right place.  I share your concern about the code addition,
> > though :)
> > 
> > I already made a patch below, but it's totally untested.
> > It'd be helpful if someone can do review and build-test it.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > ---
> > diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
> > index f0ebc97..0f810c8 100644
> > --- a/sound/aoa/codecs/tas.c
> > +++ b/sound/aoa/codecs/tas.c
> > @@ -897,6 +897,10 @@ static int tas_create(struct i2c_adapter *adapter,
> >  	client = i2c_new_device(adapter, &info);
> >  	if (!client)
> >  		return -ENODEV;
> > +	if (!client->driver) {
> > +		i2c_unregister_device(client);
> > +		return -ENODEV;
> > +	}
> >  
> >  	/*
> >  	 * Let i2c-core delete that device on driver removal.
> > diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
> > index 835fa19..473c5a6 100644
> > --- a/sound/ppc/keywest.c
> > +++ b/sound/ppc/keywest.c
> > @@ -59,6 +59,13 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
> >  	strlcpy(info.type, "keywest", I2C_NAME_SIZE);
> >  	info.addr = keywest_ctx->addr;
> >  	keywest_ctx->client = i2c_new_device(adapter, &info);
> > +	if (!keywest_ctx->client)
> > +		return -ENODEV;
> > +	if (!keywest_ctx->client->driver) {
> > +		i2c_unregister_device(keywest_ctx->client);
> > +		keywest_ctx->client = NULL;
> > +		return -ENODEV;
> > +	}
> >  	
> >  	/*
> >  	 * Let i2c-core delete that device on driver removal.
> 
> This looks good to me. Please add the following comment before the
> client->driver check in both drivers:
> 
> 	/*
> 	 * We know the driver is already loaded, so the device should be
> 	 * already bound. If not it means binding failed, and then there
> 	 * is no point in keeping the device instantiated.
> 	 */
> 
> Otherwise it's a little difficult to understand why the check is there.

Fair enough.  I applied the patch with the comment now.
Thanks!


Takashi
Jean Delvare Oct. 4, 2009, 9:35 a.m. UTC | #3
Hi Takashi,

On Thu, 01 Oct 2009 08:52:59 +0200, Takashi Iwai wrote:
> At Wed, 30 Sep 2009 18:55:05 +0200,
> Jean Delvare wrote:
> > 
> > On Wed, 30 Sep 2009 17:15:49 +0200, Takashi Iwai wrote:
> > > Yes, indeed I prefer NULL check because the user can know the error
> > > at the right place.  I share your concern about the code addition,
> > > though :)
> > > 
> > > I already made a patch below, but it's totally untested.
> > > It'd be helpful if someone can do review and build-test it.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > > ---
> > > diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
> > > index f0ebc97..0f810c8 100644
> > > --- a/sound/aoa/codecs/tas.c
> > > +++ b/sound/aoa/codecs/tas.c
> > > @@ -897,6 +897,10 @@ static int tas_create(struct i2c_adapter *adapter,
> > >  	client = i2c_new_device(adapter, &info);
> > >  	if (!client)
> > >  		return -ENODEV;
> > > +	if (!client->driver) {
> > > +		i2c_unregister_device(client);
> > > +		return -ENODEV;
> > > +	}
> > >  
> > >  	/*
> > >  	 * Let i2c-core delete that device on driver removal.
> > > diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
> > > index 835fa19..473c5a6 100644
> > > --- a/sound/ppc/keywest.c
> > > +++ b/sound/ppc/keywest.c
> > > @@ -59,6 +59,13 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
> > >  	strlcpy(info.type, "keywest", I2C_NAME_SIZE);
> > >  	info.addr = keywest_ctx->addr;
> > >  	keywest_ctx->client = i2c_new_device(adapter, &info);
> > > +	if (!keywest_ctx->client)
> > > +		return -ENODEV;
> > > +	if (!keywest_ctx->client->driver) {
> > > +		i2c_unregister_device(keywest_ctx->client);
> > > +		keywest_ctx->client = NULL;
> > > +		return -ENODEV;
> > > +	}
> > >  	
> > >  	/*
> > >  	 * Let i2c-core delete that device on driver removal.
> > 
> > This looks good to me. Please add the following comment before the
> > client->driver check in both drivers:
> > 
> > 	/*
> > 	 * We know the driver is already loaded, so the device should be
> > 	 * already bound. If not it means binding failed, and then there
> > 	 * is no point in keeping the device instantiated.
> > 	 */
> > 
> > Otherwise it's a little difficult to understand why the check is there.
> 
> Fair enough.  I applied the patch with the comment now.
> Thanks!

I see this is upstream now. While the keywest fix was essentially
theoretical, the tas one addresses a crash which really could happen,
so I think it would be worth sending to stable for 2.6.31. What do you
think? Will you take care, or do you want me to?

Thanks,
Takashi Iwai Oct. 5, 2009, 5:30 a.m. UTC | #4
At Sun, 4 Oct 2009 11:35:21 +0200,
Jean Delvare wrote:
> 
> Hi Takashi,
> 
> On Thu, 01 Oct 2009 08:52:59 +0200, Takashi Iwai wrote:
> > At Wed, 30 Sep 2009 18:55:05 +0200,
> > Jean Delvare wrote:
> > > 
> > > On Wed, 30 Sep 2009 17:15:49 +0200, Takashi Iwai wrote:
> > > > Yes, indeed I prefer NULL check because the user can know the error
> > > > at the right place.  I share your concern about the code addition,
> > > > though :)
> > > > 
> > > > I already made a patch below, but it's totally untested.
> > > > It'd be helpful if someone can do review and build-test it.
> > > > 
> > > > 
> > > > thanks,
> > > > 
> > > > Takashi
> > > > 
> > > > ---
> > > > diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
> > > > index f0ebc97..0f810c8 100644
> > > > --- a/sound/aoa/codecs/tas.c
> > > > +++ b/sound/aoa/codecs/tas.c
> > > > @@ -897,6 +897,10 @@ static int tas_create(struct i2c_adapter *adapter,
> > > >  	client = i2c_new_device(adapter, &info);
> > > >  	if (!client)
> > > >  		return -ENODEV;
> > > > +	if (!client->driver) {
> > > > +		i2c_unregister_device(client);
> > > > +		return -ENODEV;
> > > > +	}
> > > >  
> > > >  	/*
> > > >  	 * Let i2c-core delete that device on driver removal.
> > > > diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
> > > > index 835fa19..473c5a6 100644
> > > > --- a/sound/ppc/keywest.c
> > > > +++ b/sound/ppc/keywest.c
> > > > @@ -59,6 +59,13 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
> > > >  	strlcpy(info.type, "keywest", I2C_NAME_SIZE);
> > > >  	info.addr = keywest_ctx->addr;
> > > >  	keywest_ctx->client = i2c_new_device(adapter, &info);
> > > > +	if (!keywest_ctx->client)
> > > > +		return -ENODEV;
> > > > +	if (!keywest_ctx->client->driver) {
> > > > +		i2c_unregister_device(keywest_ctx->client);
> > > > +		keywest_ctx->client = NULL;
> > > > +		return -ENODEV;
> > > > +	}
> > > >  	
> > > >  	/*
> > > >  	 * Let i2c-core delete that device on driver removal.
> > > 
> > > This looks good to me. Please add the following comment before the
> > > client->driver check in both drivers:
> > > 
> > > 	/*
> > > 	 * We know the driver is already loaded, so the device should be
> > > 	 * already bound. If not it means binding failed, and then there
> > > 	 * is no point in keeping the device instantiated.
> > > 	 */
> > > 
> > > Otherwise it's a little difficult to understand why the check is there.
> > 
> > Fair enough.  I applied the patch with the comment now.
> > Thanks!
> 
> I see this is upstream now. While the keywest fix was essentially
> theoretical, the tas one addresses a crash which really could happen,
> so I think it would be worth sending to stable for 2.6.31. What do you
> think? Will you take care, or do you want me to?

Agreed, it's safer to send the patch to stable tree.
I'm going to submit it.


thanks,

Takashi
diff mbox

Patch

diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index f0ebc97..0f810c8 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -897,6 +897,10 @@  static int tas_create(struct i2c_adapter *adapter,
 	client = i2c_new_device(adapter, &info);
 	if (!client)
 		return -ENODEV;
+	if (!client->driver) {
+		i2c_unregister_device(client);
+		return -ENODEV;
+	}
 
 	/*
 	 * Let i2c-core delete that device on driver removal.
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index 835fa19..473c5a6 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -59,6 +59,13 @@  static int keywest_attach_adapter(struct i2c_adapter *adapter)
 	strlcpy(info.type, "keywest", I2C_NAME_SIZE);
 	info.addr = keywest_ctx->addr;
 	keywest_ctx->client = i2c_new_device(adapter, &info);
+	if (!keywest_ctx->client)
+		return -ENODEV;
+	if (!keywest_ctx->client->driver) {
+		i2c_unregister_device(keywest_ctx->client);
+		keywest_ctx->client = NULL;
+		return -ENODEV;
+	}
 	
 	/*
 	 * Let i2c-core delete that device on driver removal.