2021-07-30 21:42:08

by Pavel Skripkin

[permalink] [raw]
Subject: [PATCH] media: mxl111sf: change mutex_init() location

Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
mutex. The problem was in wrong mutex_init() location.

Previous mutex_init(&state->msg_lock) call was in ->init() function, but
dvb_usbv2_init() has this order of calls:

dvb_usbv2_init()
dvb_usbv2_adapter_init()
dvb_usbv2_adapter_frontend_init()
props->frontend_attach()

props->init()

Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
internally we need to initialize state->msg_lock in it to make lockdep
happy.

Reported-and-tested-by: [email protected]
Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
Signed-off-by: Pavel Skripkin <[email protected]>
---
drivers/media/usb/dvb-usb-v2/mxl111sf.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 7865fa0a8295..2e5663ffa7ce 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_device *d)
.len = sizeof(eeprom), .buf = eeprom },
};

- mutex_init(&state->msg_lock);
-
ret = get_chip_info(state);
if (mxl_fail(ret))
pr_err("failed to get chip info during probe");
@@ -979,8 +977,12 @@ static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap)
static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap)
{
int ret;
+ struct mxl111sf_state *state = d_to_priv(adap_to_d(adap));
+
pr_debug("%s\n", __func__);

+ mutex_init(&state->msg_lock);
+
ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
if (ret < 0)
return ret;
--
2.32.0



2021-08-15 08:40:22

by Sean Young

[permalink] [raw]
Subject: Re: [PATCH] media: mxl111sf: change mutex_init() location

On Sat, Jul 31, 2021 at 12:38:29AM +0300, Pavel Skripkin wrote:
> Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
> mutex. The problem was in wrong mutex_init() location.
>
> Previous mutex_init(&state->msg_lock) call was in ->init() function, but
> dvb_usbv2_init() has this order of calls:
>
> dvb_usbv2_init()
> dvb_usbv2_adapter_init()
> dvb_usbv2_adapter_frontend_init()
> props->frontend_attach()
>
> props->init()
>
> Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
> internally we need to initialize state->msg_lock in it to make lockdep
> happy.

What about the other frontends like mxl111sf_frontend_attach_dvbt? They
no longer initialize the mutex.

Thanks

Sean

>
> Reported-and-tested-by: [email protected]
> Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
> Signed-off-by: Pavel Skripkin <[email protected]>
> ---
> drivers/media/usb/dvb-usb-v2/mxl111sf.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> index 7865fa0a8295..2e5663ffa7ce 100644
> --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> @@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_device *d)
> .len = sizeof(eeprom), .buf = eeprom },
> };
>
> - mutex_init(&state->msg_lock);
> -
> ret = get_chip_info(state);
> if (mxl_fail(ret))
> pr_err("failed to get chip info during probe");
> @@ -979,8 +977,12 @@ static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap)
> static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap)
> {
> int ret;
> + struct mxl111sf_state *state = d_to_priv(adap_to_d(adap));
> +
> pr_debug("%s\n", __func__);
>
> + mutex_init(&state->msg_lock);
> +
> ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
> if (ret < 0)
> return ret;
> --
> 2.32.0

2021-08-15 08:53:28

by Pavel Skripkin

[permalink] [raw]
Subject: Re: [PATCH] media: mxl111sf: change mutex_init() location

On 8/15/21 11:37 AM, Sean Young wrote:
> On Sat, Jul 31, 2021 at 12:38:29AM +0300, Pavel Skripkin wrote:
>> Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
>> mutex. The problem was in wrong mutex_init() location.
>>
>> Previous mutex_init(&state->msg_lock) call was in ->init() function, but
>> dvb_usbv2_init() has this order of calls:
>>
>> dvb_usbv2_init()
>> dvb_usbv2_adapter_init()
>> dvb_usbv2_adapter_frontend_init()
>> props->frontend_attach()
>>
>> props->init()
>>
>> Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
>> internally we need to initialize state->msg_lock in it to make lockdep
>> happy.
>
> What about the other frontends like mxl111sf_frontend_attach_dvbt? They
> no longer initialize the mutex.
>
Good point. I see, that all other frontends also call
mxl111sf_ctrl_msg() inside ->frontend_attach() call.

I think, that fixing dvb-usb core is not good idea, so, I will add
mutex_init() call inside all frontends, which use mxl111sf_init().

What do you think about it?


With regards,
Pavel Skripkin

2021-08-15 09:09:09

by Pavel Skripkin

[permalink] [raw]
Subject: Re: [PATCH] media: mxl111sf: change mutex_init() location

On 8/15/21 11:49 AM, Pavel Skripkin wrote:
> On 8/15/21 11:37 AM, Sean Young wrote:
>> On Sat, Jul 31, 2021 at 12:38:29AM +0300, Pavel Skripkin wrote:
>>> Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
>>> mutex. The problem was in wrong mutex_init() location.
>>>
>>> Previous mutex_init(&state->msg_lock) call was in ->init() function, but
>>> dvb_usbv2_init() has this order of calls:
>>>
>>> dvb_usbv2_init()
>>> dvb_usbv2_adapter_init()
>>> dvb_usbv2_adapter_frontend_init()
>>> props->frontend_attach()
>>>
>>> props->init()
>>>
>>> Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
>>> internally we need to initialize state->msg_lock in it to make lockdep
>>> happy.
>>
>> What about the other frontends like mxl111sf_frontend_attach_dvbt? They
>> no longer initialize the mutex.
>>
> Good point. I see, that all other frontends also call
> mxl111sf_ctrl_msg() inside ->frontend_attach() call.
>
> I think, that fixing dvb-usb core is not good idea, so, I will add
> mutex_init() call inside all frontends, which use mxl111sf_init().
>
> What do you think about it?
>
>


Something like this should work. Helper is just to not copy-paste code
parts. Build tested against v5.14-rc5


diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 7865fa0a8295..db1ad3815cd5 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -49,6 +49,13 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position
(0=auto, 1=ext, 2=int).");

DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

+static inline void mxl111sf_init_msg_mutex(struct dvb_usb_adapter *adap)
+{
+ struct mxl111sf_state *state = d_to_priv(adap_to_d(adap));
+
+ mutex_init(&state->msg_lock);
+}
+
int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
@@ -931,8 +938,6 @@ static int mxl111sf_init(struct dvb_usb_device *d)
.len = sizeof(eeprom), .buf = eeprom },
};

- mutex_init(&state->msg_lock);
-
ret = get_chip_info(state);
if (mxl_fail(ret))
pr_err("failed to get chip info during probe");
@@ -963,16 +968,19 @@ static int mxl111sf_init(struct dvb_usb_device *d)

static int mxl111sf_frontend_attach_dvbt(struct dvb_usb_adapter *adap)
{
+ mxl111sf_init_msg_mutex(adap);
return mxl111sf_attach_demod(adap, 0);
}

static int mxl111sf_frontend_attach_atsc(struct dvb_usb_adapter *adap)
{
+ mxl111sf_init_msg_mutex(adap);
return mxl111sf_lgdt3305_frontend_attach(adap, 0);
}

static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap)
{
+ mxl111sf_init_msg_mutex(adap);
return mxl111sf_lg2160_frontend_attach(adap, 0);
}

@@ -981,6 +989,7 @@ static int mxl111sf_frontend_attach_atsc_mh(struct
dvb_usb_adapter *adap)
int ret;
pr_debug("%s\n", __func__);

+ mxl111sf_init_msg_mutex(adap);
ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
if (ret < 0)
return ret;
@@ -1001,6 +1010,7 @@ static int mxl111sf_frontend_attach_mercury(struct
dvb_usb_adapter *adap)
int ret;
pr_debug("%s\n", __func__);

+ mxl111sf_init_msg_mutex(adap);
ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
if (ret < 0)
return ret;
@@ -1021,6 +1031,7 @@ static int
mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap)
int ret;
pr_debug("%s\n", __func__);

+ mxl111sf_init_msg_mutex(adap);
ret = mxl111sf_attach_demod(adap, 0);
if (ret < 0)
return ret;



With regards,
Pavel Skripkin

2021-08-19 09:31:41

by Sean Young

[permalink] [raw]
Subject: Re: [PATCH] media: mxl111sf: change mutex_init() location

On Sun, Aug 15, 2021 at 12:06:16PM +0300, Pavel Skripkin wrote:
> On 8/15/21 11:49 AM, Pavel Skripkin wrote:
> > On 8/15/21 11:37 AM, Sean Young wrote:
> > > On Sat, Jul 31, 2021 at 12:38:29AM +0300, Pavel Skripkin wrote:
> > > > Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
> > > > mutex. The problem was in wrong mutex_init() location.
> > > >
> > > > Previous mutex_init(&state->msg_lock) call was in ->init() function, but
> > > > dvb_usbv2_init() has this order of calls:
> > > >
> > > > dvb_usbv2_init()
> > > > dvb_usbv2_adapter_init()
> > > > dvb_usbv2_adapter_frontend_init()
> > > > props->frontend_attach()
> > > >
> > > > props->init()
> > > >
> > > > Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
> > > > internally we need to initialize state->msg_lock in it to make lockdep
> > > > happy.
> > >
> > > What about the other frontends like mxl111sf_frontend_attach_dvbt? They
> > > no longer initialize the mutex.
> > >
> > Good point. I see, that all other frontends also call
> > mxl111sf_ctrl_msg() inside ->frontend_attach() call.
> >
> > I think, that fixing dvb-usb core is not good idea, so, I will add
> > mutex_init() call inside all frontends, which use mxl111sf_init().
> >
> > What do you think about it?
> >
> >
>
>
> Something like this should work. Helper is just to not copy-paste code
> parts. Build tested against v5.14-rc5

How about creating a dvb_usb_device_properties probe function and
initializing the mutex init there?


Sean

>
>
> diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> index 7865fa0a8295..db1ad3815cd5 100644
> --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
> @@ -49,6 +49,13 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position
> (0=auto, 1=ext, 2=int).");
>
> DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>
> +static inline void mxl111sf_init_msg_mutex(struct dvb_usb_adapter *adap)
> +{
> + struct mxl111sf_state *state = d_to_priv(adap_to_d(adap));
> +
> + mutex_init(&state->msg_lock);
> +}
> +
> int mxl111sf_ctrl_msg(struct mxl111sf_state *state,
> u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
> {
> @@ -931,8 +938,6 @@ static int mxl111sf_init(struct dvb_usb_device *d)
> .len = sizeof(eeprom), .buf = eeprom },
> };
>
> - mutex_init(&state->msg_lock);
> -
> ret = get_chip_info(state);
> if (mxl_fail(ret))
> pr_err("failed to get chip info during probe");
> @@ -963,16 +968,19 @@ static int mxl111sf_init(struct dvb_usb_device *d)
>
> static int mxl111sf_frontend_attach_dvbt(struct dvb_usb_adapter *adap)
> {
> + mxl111sf_init_msg_mutex(adap);
> return mxl111sf_attach_demod(adap, 0);
> }
>
> static int mxl111sf_frontend_attach_atsc(struct dvb_usb_adapter *adap)
> {
> + mxl111sf_init_msg_mutex(adap);
> return mxl111sf_lgdt3305_frontend_attach(adap, 0);
> }
>
> static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap)
> {
> + mxl111sf_init_msg_mutex(adap);
> return mxl111sf_lg2160_frontend_attach(adap, 0);
> }
>
> @@ -981,6 +989,7 @@ static int mxl111sf_frontend_attach_atsc_mh(struct
> dvb_usb_adapter *adap)
> int ret;
> pr_debug("%s\n", __func__);
>
> + mxl111sf_init_msg_mutex(adap);
> ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
> if (ret < 0)
> return ret;
> @@ -1001,6 +1010,7 @@ static int mxl111sf_frontend_attach_mercury(struct
> dvb_usb_adapter *adap)
> int ret;
> pr_debug("%s\n", __func__);
>
> + mxl111sf_init_msg_mutex(adap);
> ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
> if (ret < 0)
> return ret;
> @@ -1021,6 +1031,7 @@ static int mxl111sf_frontend_attach_mercury_mh(struct
> dvb_usb_adapter *adap)
> int ret;
> pr_debug("%s\n", __func__);
>
> + mxl111sf_init_msg_mutex(adap);
> ret = mxl111sf_attach_demod(adap, 0);
> if (ret < 0)
> return ret;
>
>
>
> With regards,
> Pavel Skripkin

2021-08-19 09:33:44

by Pavel Skripkin

[permalink] [raw]
Subject: Re: [PATCH] media: mxl111sf: change mutex_init() location

On 8/19/21 12:29 PM, Sean Young wrote:
> On Sun, Aug 15, 2021 at 12:06:16PM +0300, Pavel Skripkin wrote:
>> On 8/15/21 11:49 AM, Pavel Skripkin wrote:
>> > On 8/15/21 11:37 AM, Sean Young wrote:
>> > > On Sat, Jul 31, 2021 at 12:38:29AM +0300, Pavel Skripkin wrote:
>> > > > Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
>> > > > mutex. The problem was in wrong mutex_init() location.
>> > > >
>> > > > Previous mutex_init(&state->msg_lock) call was in ->init() function, but
>> > > > dvb_usbv2_init() has this order of calls:
>> > > >
>> > > > dvb_usbv2_init()
>> > > > dvb_usbv2_adapter_init()
>> > > > dvb_usbv2_adapter_frontend_init()
>> > > > props->frontend_attach()
>> > > >
>> > > > props->init()
>> > > >
>> > > > Since mxl111sf_frontend_attach_atsc_mh() calls mxl111sf_ctrl_msg()
>> > > > internally we need to initialize state->msg_lock in it to make lockdep
>> > > > happy.
>> > >
>> > > What about the other frontends like mxl111sf_frontend_attach_dvbt? They
>> > > no longer initialize the mutex.
>> > >
>> > Good point. I see, that all other frontends also call
>> > mxl111sf_ctrl_msg() inside ->frontend_attach() call.
>> >
>> > I think, that fixing dvb-usb core is not good idea, so, I will add
>> > mutex_init() call inside all frontends, which use mxl111sf_init().
>> >
>> > What do you think about it?
>> >
>> >
>>
>>
>> Something like this should work. Helper is just to not copy-paste code
>> parts. Build tested against v5.14-rc5
>
> How about creating a dvb_usb_device_properties probe function and
> initializing the mutex init there?
>
>

Sounds reasonable. Will do it in v2, thank you!



With regards,
Pavel Skripkin

2021-08-19 10:40:24

by Pavel Skripkin

[permalink] [raw]
Subject: [PATCH v2] media: mxl111sf: change mutex_init() location

Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
mutex. The problem was in wrong mutex_init() location.

Previous mutex_init(&state->msg_lock) call was in ->init() function, but
dvb_usbv2_init() has this order of calls:

dvb_usbv2_init()
dvb_usbv2_adapter_init()
dvb_usbv2_adapter_frontend_init()
props->frontend_attach()

props->init()

Since mxl111sf_* devices call mxl111sf_ctrl_msg() in ->frontend_attach()
internally we need to initialize state->msg_lock before
frontend_attach(). To achieve it, ->probe() call added to all mxl111sf_*
devices, which will simply initiaize mutex.

Reported-and-tested-by: [email protected]
Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
Signed-off-by: Pavel Skripkin <[email protected]>
---

Changes in v2:
Addressed same bug in all mxl111sf_* devices by adding ->probe
call

---
drivers/media/usb/dvb-usb-v2/mxl111sf.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 7865fa0a8295..b9714ce994d1 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -1074,6 +1074,14 @@ static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe,
return 0;
}

+static int mxl111sf_probe(struct dvb_usb_device *dev)
+{
+ struct mxl111sf_state *state = d_to_priv(dev);
+
+ mutex_init(&state->msg_lock);
+ return 0;
+}
+
static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
.driver_name = KBUILD_MODNAME,
.owner = THIS_MODULE,
@@ -1083,6 +1091,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_dvbt,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1124,6 +1133,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_atsc,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1165,6 +1175,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mh,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1233,6 +1244,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_atsc_mh,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1311,6 +1323,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mercury,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1381,6 +1394,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mercury_mh,
.tuner_attach = mxl111sf_attach_tuner,
--
2.32.0

2021-08-19 10:45:13

by Pavel Skripkin

[permalink] [raw]
Subject: [PATCH v3] media: mxl111sf: change mutex_init() location

Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
mutex. The problem was in wrong mutex_init() location.

Previous mutex_init(&state->msg_lock) call was in ->init() function, but
dvb_usbv2_init() has this order of calls:

dvb_usbv2_init()
dvb_usbv2_adapter_init()
dvb_usbv2_adapter_frontend_init()
props->frontend_attach()

props->init()

Since mxl111sf_* devices call mxl111sf_ctrl_msg() in ->frontend_attach()
internally we need to initialize state->msg_lock before
frontend_attach(). To achieve it, ->probe() call added to all mxl111sf_*
devices, which will simply initiaize mutex.

Reported-and-tested-by: [email protected]
Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
Signed-off-by: Pavel Skripkin <[email protected]>
---

Changes in v3:
I forgot to remove mutex_init() call from ->init()

Changes in v2:
Addressed same bug in all mxl111sf_* devices by adding ->probe
call

---
drivers/media/usb/dvb-usb-v2/mxl111sf.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 7865fa0a8295..cd5861a30b6f 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_device *d)
.len = sizeof(eeprom), .buf = eeprom },
};

- mutex_init(&state->msg_lock);
-
ret = get_chip_info(state);
if (mxl_fail(ret))
pr_err("failed to get chip info during probe");
@@ -1074,6 +1072,14 @@ static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe,
return 0;
}

+static int mxl111sf_probe(struct dvb_usb_device *dev)
+{
+ struct mxl111sf_state *state = d_to_priv(dev);
+
+ mutex_init(&state->msg_lock);
+ return 0;
+}
+
static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
.driver_name = KBUILD_MODNAME,
.owner = THIS_MODULE,
@@ -1083,6 +1089,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_dvbt,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1124,6 +1131,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_atsc,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1165,6 +1173,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mh,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1233,6 +1242,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_atsc_mh,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1311,6 +1321,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mercury,
.tuner_attach = mxl111sf_attach_tuner,
@@ -1381,6 +1392,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = {
.generic_bulk_ctrl_endpoint = 0x02,
.generic_bulk_ctrl_endpoint_response = 0x81,

+ .probe = mxl111sf_probe,
.i2c_algo = &mxl111sf_i2c_algo,
.frontend_attach = mxl111sf_frontend_attach_mercury_mh,
.tuner_attach = mxl111sf_attach_tuner,
--
2.32.0

2021-09-12 15:52:51

by Pavel Skripkin

[permalink] [raw]
Subject: Re: [PATCH v3] media: mxl111sf: change mutex_init() location

On 8/19/21 13:42, Pavel Skripkin wrote:
> Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
> mutex. The problem was in wrong mutex_init() location.
>
> Previous mutex_init(&state->msg_lock) call was in ->init() function, but
> dvb_usbv2_init() has this order of calls:
>
> dvb_usbv2_init()
> dvb_usbv2_adapter_init()
> dvb_usbv2_adapter_frontend_init()
> props->frontend_attach()
>
> props->init()
>
> Since mxl111sf_* devices call mxl111sf_ctrl_msg() in ->frontend_attach()
> internally we need to initialize state->msg_lock before
> frontend_attach(). To achieve it, ->probe() call added to all mxl111sf_*
> devices, which will simply initiaize mutex.
>
> Reported-and-tested-by: [email protected]
> Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
> Signed-off-by: Pavel Skripkin <[email protected]>

Hi, Sean!

Did you have a chance to review this patch? Thank you :)


With regards,
Pavel Skripkin

2021-09-15 16:41:02

by Sean Young

[permalink] [raw]
Subject: Re: [PATCH v3] media: mxl111sf: change mutex_init() location

On Sun, Sep 12, 2021 at 06:49:52PM +0300, Pavel Skripkin wrote:
> On 8/19/21 13:42, Pavel Skripkin wrote:
> > Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
> > mutex. The problem was in wrong mutex_init() location.
> >
> > Previous mutex_init(&state->msg_lock) call was in ->init() function, but
> > dvb_usbv2_init() has this order of calls:
> >
> > dvb_usbv2_init()
> > dvb_usbv2_adapter_init()
> > dvb_usbv2_adapter_frontend_init()
> > props->frontend_attach()
> >
> > props->init()
> >
> > Since mxl111sf_* devices call mxl111sf_ctrl_msg() in ->frontend_attach()
> > internally we need to initialize state->msg_lock before
> > frontend_attach(). To achieve it, ->probe() call added to all mxl111sf_*
> > devices, which will simply initiaize mutex.
> >
> > Reported-and-tested-by: [email protected]
> > Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
> > Signed-off-by: Pavel Skripkin <[email protected]>
>
> Hi, Sean!
>
> Did you have a chance to review this patch? Thank you :)

Sorry during the merge window (from -rc6 to -rc1) I don't tend to look
at patches. Looks good to me, I'll merge it.

Thanks

Sean