lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 163/563] media: dw2102: Fix use after free
    Date
    From: Anton Vasilyev <vasilyev@ispras.ru>

    [ Upstream commit 589a9f0eb799f77de2c09583bf5bad221fa5d685 ]

    dvb_usb_device_init stores parts of properties at d->props
    and d->desc and uses it on dvb_usb_device_exit.
    Free of properties on module probe leads to use after free.
    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204597

    The patch makes properties static instead of allocated on heap to prevent
    memleak and use after free.
    Also fixes s421_properties.devices initialization to have 2 element
    instead of 6 copied from p7500_properties.

    [mchehab: fix function call alignments]
    Link: https://lore.kernel.org/linux-media/20190822104147.4420-1-vasilyev@ispras.ru
    Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru>
    Fixes: 299c7007e936 ("media: dw2102: Fix memleak on sequence of probes")
    Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/media/usb/dvb-usb/dw2102.c | 338 ++++++++++++++++++-----------
    1 file changed, 215 insertions(+), 123 deletions(-)

    diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
    index a27a684403252..aa929db56db1f 100644
    --- a/drivers/media/usb/dvb-usb/dw2102.c
    +++ b/drivers/media/usb/dvb-usb/dw2102.c
    @@ -2148,46 +2148,153 @@ static struct dvb_usb_device_properties s6x0_properties = {
    }
    };

    -static const struct dvb_usb_device_description d1100 = {
    - "Prof 1100 USB ",
    - {&dw2102_table[PROF_1100], NULL},
    - {NULL},
    -};
    +static struct dvb_usb_device_properties p1100_properties = {
    + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
    + .usb_ctrl = DEVICE_SPECIFIC,
    + .size_of_priv = sizeof(struct dw2102_state),
    + .firmware = P1100_FIRMWARE,
    + .no_reconnect = 1,

    -static const struct dvb_usb_device_description d660 = {
    - "TeVii S660 USB",
    - {&dw2102_table[TEVII_S660], NULL},
    - {NULL},
    -};
    + .i2c_algo = &s6x0_i2c_algo,
    + .rc.core = {
    + .rc_interval = 150,
    + .rc_codes = RC_MAP_TBS_NEC,
    + .module_name = "dw2102",
    + .allowed_protos = RC_PROTO_BIT_NEC,
    + .rc_query = prof_rc_query,
    + },

    -static const struct dvb_usb_device_description d480_1 = {
    - "TeVii S480.1 USB",
    - {&dw2102_table[TEVII_S480_1], NULL},
    - {NULL},
    + .generic_bulk_ctrl_endpoint = 0x81,
    + .num_adapters = 1,
    + .download_firmware = dw2102_load_firmware,
    + .read_mac_address = s6x0_read_mac_address,
    + .adapter = {
    + {
    + .num_frontends = 1,
    + .fe = {{
    + .frontend_attach = stv0288_frontend_attach,
    + .stream = {
    + .type = USB_BULK,
    + .count = 8,
    + .endpoint = 0x82,
    + .u = {
    + .bulk = {
    + .buffersize = 4096,
    + }
    + }
    + },
    + } },
    + }
    + },
    + .num_device_descs = 1,
    + .devices = {
    + {"Prof 1100 USB ",
    + {&dw2102_table[PROF_1100], NULL},
    + {NULL},
    + },
    + }
    };

    -static const struct dvb_usb_device_description d480_2 = {
    - "TeVii S480.2 USB",
    - {&dw2102_table[TEVII_S480_2], NULL},
    - {NULL},
    -};
    +static struct dvb_usb_device_properties s660_properties = {
    + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
    + .usb_ctrl = DEVICE_SPECIFIC,
    + .size_of_priv = sizeof(struct dw2102_state),
    + .firmware = S660_FIRMWARE,
    + .no_reconnect = 1,

    -static const struct dvb_usb_device_description d7500 = {
    - "Prof 7500 USB DVB-S2",
    - {&dw2102_table[PROF_7500], NULL},
    - {NULL},
    -};
    + .i2c_algo = &s6x0_i2c_algo,
    + .rc.core = {
    + .rc_interval = 150,
    + .rc_codes = RC_MAP_TEVII_NEC,
    + .module_name = "dw2102",
    + .allowed_protos = RC_PROTO_BIT_NEC,
    + .rc_query = dw2102_rc_query,
    + },

    -static const struct dvb_usb_device_description d421 = {
    - "TeVii S421 PCI",
    - {&dw2102_table[TEVII_S421], NULL},
    - {NULL},
    + .generic_bulk_ctrl_endpoint = 0x81,
    + .num_adapters = 1,
    + .download_firmware = dw2102_load_firmware,
    + .read_mac_address = s6x0_read_mac_address,
    + .adapter = {
    + {
    + .num_frontends = 1,
    + .fe = {{
    + .frontend_attach = ds3000_frontend_attach,
    + .stream = {
    + .type = USB_BULK,
    + .count = 8,
    + .endpoint = 0x82,
    + .u = {
    + .bulk = {
    + .buffersize = 4096,
    + }
    + }
    + },
    + } },
    + }
    + },
    + .num_device_descs = 3,
    + .devices = {
    + {"TeVii S660 USB",
    + {&dw2102_table[TEVII_S660], NULL},
    + {NULL},
    + },
    + {"TeVii S480.1 USB",
    + {&dw2102_table[TEVII_S480_1], NULL},
    + {NULL},
    + },
    + {"TeVii S480.2 USB",
    + {&dw2102_table[TEVII_S480_2], NULL},
    + {NULL},
    + },
    + }
    };

    -static const struct dvb_usb_device_description d632 = {
    - "TeVii S632 USB",
    - {&dw2102_table[TEVII_S632], NULL},
    - {NULL},
    +static struct dvb_usb_device_properties p7500_properties = {
    + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
    + .usb_ctrl = DEVICE_SPECIFIC,
    + .size_of_priv = sizeof(struct dw2102_state),
    + .firmware = P7500_FIRMWARE,
    + .no_reconnect = 1,
    +
    + .i2c_algo = &s6x0_i2c_algo,
    + .rc.core = {
    + .rc_interval = 150,
    + .rc_codes = RC_MAP_TBS_NEC,
    + .module_name = "dw2102",
    + .allowed_protos = RC_PROTO_BIT_NEC,
    + .rc_query = prof_rc_query,
    + },
    +
    + .generic_bulk_ctrl_endpoint = 0x81,
    + .num_adapters = 1,
    + .download_firmware = dw2102_load_firmware,
    + .read_mac_address = s6x0_read_mac_address,
    + .adapter = {
    + {
    + .num_frontends = 1,
    + .fe = {{
    + .frontend_attach = prof_7500_frontend_attach,
    + .stream = {
    + .type = USB_BULK,
    + .count = 8,
    + .endpoint = 0x82,
    + .u = {
    + .bulk = {
    + .buffersize = 4096,
    + }
    + }
    + },
    + } },
    + }
    + },
    + .num_device_descs = 1,
    + .devices = {
    + {"Prof 7500 USB DVB-S2",
    + {&dw2102_table[PROF_7500], NULL},
    + {NULL},
    + },
    + }
    };

    static struct dvb_usb_device_properties su3000_properties = {
    @@ -2267,6 +2374,59 @@ static struct dvb_usb_device_properties su3000_properties = {
    }
    };

    +static struct dvb_usb_device_properties s421_properties = {
    + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
    + .usb_ctrl = DEVICE_SPECIFIC,
    + .size_of_priv = sizeof(struct dw2102_state),
    + .power_ctrl = su3000_power_ctrl,
    + .num_adapters = 1,
    + .identify_state = su3000_identify_state,
    + .i2c_algo = &su3000_i2c_algo,
    +
    + .rc.core = {
    + .rc_interval = 150,
    + .rc_codes = RC_MAP_SU3000,
    + .module_name = "dw2102",
    + .allowed_protos = RC_PROTO_BIT_RC5,
    + .rc_query = su3000_rc_query,
    + },
    +
    + .read_mac_address = su3000_read_mac_address,
    +
    + .generic_bulk_ctrl_endpoint = 0x01,
    +
    + .adapter = {
    + {
    + .num_frontends = 1,
    + .fe = {{
    + .streaming_ctrl = su3000_streaming_ctrl,
    + .frontend_attach = m88rs2000_frontend_attach,
    + .stream = {
    + .type = USB_BULK,
    + .count = 8,
    + .endpoint = 0x82,
    + .u = {
    + .bulk = {
    + .buffersize = 4096,
    + }
    + }
    + }
    + } },
    + }
    + },
    + .num_device_descs = 2,
    + .devices = {
    + { "TeVii S421 PCI",
    + { &dw2102_table[TEVII_S421], NULL },
    + { NULL },
    + },
    + { "TeVii S632 USB",
    + { &dw2102_table[TEVII_S632], NULL },
    + { NULL },
    + },
    + }
    +};
    +
    static struct dvb_usb_device_properties t220_properties = {
    .caps = DVB_USB_IS_AN_I2C_ADAPTER,
    .usb_ctrl = DEVICE_SPECIFIC,
    @@ -2384,101 +2544,33 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = {
    static int dw2102_probe(struct usb_interface *intf,
    const struct usb_device_id *id)
    {
    - int retval = -ENOMEM;
    - struct dvb_usb_device_properties *p1100;
    - struct dvb_usb_device_properties *s660;
    - struct dvb_usb_device_properties *p7500;
    - struct dvb_usb_device_properties *s421;
    -
    - p1100 = kmemdup(&s6x0_properties,
    - sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
    - if (!p1100)
    - goto err0;
    -
    - /* copy default structure */
    - /* fill only different fields */
    - p1100->firmware = P1100_FIRMWARE;
    - p1100->devices[0] = d1100;
    - p1100->rc.core.rc_query = prof_rc_query;
    - p1100->rc.core.rc_codes = RC_MAP_TBS_NEC;
    - p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
    -
    - s660 = kmemdup(&s6x0_properties,
    - sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
    - if (!s660)
    - goto err1;
    -
    - s660->firmware = S660_FIRMWARE;
    - s660->num_device_descs = 3;
    - s660->devices[0] = d660;
    - s660->devices[1] = d480_1;
    - s660->devices[2] = d480_2;
    - s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
    -
    - p7500 = kmemdup(&s6x0_properties,
    - sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
    - if (!p7500)
    - goto err2;
    -
    - p7500->firmware = P7500_FIRMWARE;
    - p7500->devices[0] = d7500;
    - p7500->rc.core.rc_query = prof_rc_query;
    - p7500->rc.core.rc_codes = RC_MAP_TBS_NEC;
    - p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
    -
    -
    - s421 = kmemdup(&su3000_properties,
    - sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
    - if (!s421)
    - goto err3;
    -
    - s421->num_device_descs = 2;
    - s421->devices[0] = d421;
    - s421->devices[1] = d632;
    - s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach;
    -
    - if (0 == dvb_usb_device_init(intf, &dw2102_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &dw2104_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &dw3101_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &s6x0_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, p1100,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, s660,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, p7500,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, s421,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &su3000_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &t220_properties,
    - THIS_MODULE, NULL, adapter_nr) ||
    - 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties,
    - THIS_MODULE, NULL, adapter_nr)) {
    -
    - /* clean up copied properties */
    - kfree(s421);
    - kfree(p7500);
    - kfree(s660);
    - kfree(p1100);
    + if (!(dvb_usb_device_init(intf, &dw2102_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &dw2104_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &dw3101_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &s6x0_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &p1100_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &s660_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &p7500_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &s421_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &su3000_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &t220_properties,
    + THIS_MODULE, NULL, adapter_nr) &&
    + dvb_usb_device_init(intf, &tt_s2_4600_properties,
    + THIS_MODULE, NULL, adapter_nr))) {

    return 0;
    }

    - retval = -ENODEV;
    - kfree(s421);
    -err3:
    - kfree(p7500);
    -err2:
    - kfree(s660);
    -err1:
    - kfree(p1100);
    -err0:
    - return retval;
    + return -ENODEV;
    }

    static void dw2102_disconnect(struct usb_interface *intf)
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-01-25 01:14    [W:2.081 / U:1.224 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site