[PATCH] media: dw2102: Fix use after free
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. Signed-off-by: Anton Vasilyev Fixes: 299c7007e936 ("media: dw2102: Fix memleak on sequence of probes") --- 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 b960abd00d48..7ea3aa0fee40 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2098,46 +2098,153 @@ static struct dvb_usb_device_properties s6x0_properties = { } }; -static const struct dvb_usb_device_description d1100 = { - "Prof 1100 USB ", - {_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", - {_table[TEVII_S660], NULL}, - {NULL}, -}; + .i2c_algo = _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", - {_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 ", + {_table[PROF_1100], NULL}, + {NULL}, + }, + } }; -static const struct dvb_usb_device_description d480_2 = { - "TeVii S480.2 USB", - {_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", - {_table[PROF_7500], NULL}, - {NULL}, -}; + .i2c_algo = _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", - {_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 = { +
[PATCH] usb: gadget: fotg210-udc: Fix memory leak of fotg210->ep[i]
There is no deallocation of fotg210->ep[i] elements, allocated at fotg210_udc_probe. The patch adds deallocation of fotg210->ep array elements and simplifies error path of fotg210_udc_probe(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/usb/gadget/udc/fotg210-udc.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index 53a48f561458..587c5037ff07 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -1063,12 +1063,15 @@ static const struct usb_gadget_ops fotg210_gadget_ops = { static int fotg210_udc_remove(struct platform_device *pdev) { struct fotg210_udc *fotg210 = platform_get_drvdata(pdev); + int i; usb_del_gadget_udc(>gadget); iounmap(fotg210->reg); free_irq(platform_get_irq(pdev, 0), fotg210); fotg210_ep_free_request(>ep[0]->ep, fotg210->ep0_req); + for (i = 0; i < FOTG210_MAX_NUM_EP; i++) + kfree(fotg210->ep[i]); kfree(fotg210); return 0; @@ -1099,7 +1102,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) /* initialize udc */ fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL); if (fotg210 == NULL) - goto err_alloc; + goto err; for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL); @@ -,7 +1114,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210->reg = ioremap(res->start, resource_size(res)); if (fotg210->reg == NULL) { pr_err("ioremap error.\n"); - goto err_map; + goto err_alloc; } spin_lock_init(>lock); @@ -1159,7 +1162,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210->ep0_req = fotg210_ep_alloc_request(>ep[0]->ep, GFP_KERNEL); if (fotg210->ep0_req == NULL) - goto err_req; + goto err_map; fotg210_init(fotg210); @@ -1187,12 +1190,14 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210_ep_free_request(>ep[0]->ep, fotg210->ep0_req); err_map: - if (fotg210->reg) - iounmap(fotg210->reg); + iounmap(fotg210->reg); err_alloc: + for (i = 0; i < FOTG210_MAX_NUM_EP; i++) + kfree(fotg210->ep[i]); kfree(fotg210); +err: return ret; } -- 2.18.0
[PATCH] usb: gadget: fotg210-udc: Fix memory leak of fotg210->ep[i]
There is no deallocation of fotg210->ep[i] elements, allocated at fotg210_udc_probe. The patch adds deallocation of fotg210->ep array elements and simplifies error path of fotg210_udc_probe(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/usb/gadget/udc/fotg210-udc.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index 53a48f561458..587c5037ff07 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -1063,12 +1063,15 @@ static const struct usb_gadget_ops fotg210_gadget_ops = { static int fotg210_udc_remove(struct platform_device *pdev) { struct fotg210_udc *fotg210 = platform_get_drvdata(pdev); + int i; usb_del_gadget_udc(>gadget); iounmap(fotg210->reg); free_irq(platform_get_irq(pdev, 0), fotg210); fotg210_ep_free_request(>ep[0]->ep, fotg210->ep0_req); + for (i = 0; i < FOTG210_MAX_NUM_EP; i++) + kfree(fotg210->ep[i]); kfree(fotg210); return 0; @@ -1099,7 +1102,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) /* initialize udc */ fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL); if (fotg210 == NULL) - goto err_alloc; + goto err; for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL); @@ -,7 +1114,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210->reg = ioremap(res->start, resource_size(res)); if (fotg210->reg == NULL) { pr_err("ioremap error.\n"); - goto err_map; + goto err_alloc; } spin_lock_init(>lock); @@ -1159,7 +1162,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210->ep0_req = fotg210_ep_alloc_request(>ep[0]->ep, GFP_KERNEL); if (fotg210->ep0_req == NULL) - goto err_req; + goto err_map; fotg210_init(fotg210); @@ -1187,12 +1190,14 @@ static int fotg210_udc_probe(struct platform_device *pdev) fotg210_ep_free_request(>ep[0]->ep, fotg210->ep0_req); err_map: - if (fotg210->reg) - iounmap(fotg210->reg); + iounmap(fotg210->reg); err_alloc: + for (i = 0; i < FOTG210_MAX_NUM_EP; i++) + kfree(fotg210->ep[i]); kfree(fotg210); +err: return ret; } -- 2.18.0
[PATCH v2] serial: mxs-auart: Fix potential infinite loop
On the error path of mxs_auart_request_gpio_irq() is performed backward iterating with index i of enum type. Underline enum type may be unsigned char. In this case check (--i >= 0) will be always true and error handling goes into infinite loop. The patch changes the check so that it is valid for signed and unsigned types. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: mistype in patch as result of combination of different fixes. Change comment and leave enum type. --- drivers/tty/serial/mxs-auart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 76aa289652f7..27235a526cce 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1634,8 +1634,9 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) /* * If something went wrong, rollback. +* Be careful: i may be unsigned. */ - while (err && (--i >= 0)) + while (err && (i-- > 0)) if (irq[i] >= 0) free_irq(irq[i], s); -- 2.18.0
[PATCH v2] serial: mxs-auart: Fix potential infinite loop
On the error path of mxs_auart_request_gpio_irq() is performed backward iterating with index i of enum type. Underline enum type may be unsigned char. In this case check (--i >= 0) will be always true and error handling goes into infinite loop. The patch changes the check so that it is valid for signed and unsigned types. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: mistype in patch as result of combination of different fixes. Change comment and leave enum type. --- drivers/tty/serial/mxs-auart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 76aa289652f7..27235a526cce 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1634,8 +1634,9 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) /* * If something went wrong, rollback. +* Be careful: i may be unsigned. */ - while (err && (--i >= 0)) + while (err && (i-- > 0)) if (irq[i] >= 0) free_irq(irq[i], s); -- 2.18.0
[PATCH] serial: mxs-auart: Fix potential infinite loop
On the error path of mxs_auart_request_gpio_irq() is performed backward iterating with index i of enum type. Underline enum type may be unsigned char. In this case check (--i >= 0) will be always true and error handling goes into infinite loop. The patch changes type of index variable to int. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/tty/serial/mxs-auart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 76aa289652f7..89b34bb09cde 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1617,7 +1617,7 @@ static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s) static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) { int *irq = s->gpio_irq; - enum mctrl_gpio_idx i; + int i; int err = 0; for (i = 0; (i < UART_GPIO_MAX) && !err; i++) { @@ -1634,8 +1634,9 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) /* * If something went wrong, rollback. +* Be careful: i may be unsigned. */ - while (err && (--i >= 0)) + while (err && (i-- > 0)) if (irq[i] >= 0) free_irq(irq[i], s); -- 2.18.0
[PATCH] serial: mxs-auart: Fix potential infinite loop
On the error path of mxs_auart_request_gpio_irq() is performed backward iterating with index i of enum type. Underline enum type may be unsigned char. In this case check (--i >= 0) will be always true and error handling goes into infinite loop. The patch changes type of index variable to int. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/tty/serial/mxs-auart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 76aa289652f7..89b34bb09cde 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1617,7 +1617,7 @@ static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s) static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) { int *irq = s->gpio_irq; - enum mctrl_gpio_idx i; + int i; int err = 0; for (i = 0; (i < UART_GPIO_MAX) && !err; i++) { @@ -1634,8 +1634,9 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) /* * If something went wrong, rollback. +* Be careful: i may be unsigned. */ - while (err && (--i >= 0)) + while (err && (i-- > 0)) if (irq[i] >= 0) free_irq(irq[i], s); -- 2.18.0
[PATCH] pinctrl: axp209: Fix NULL pointer dereference after allocation
There is no check that allocation in axp20x_funcs_groups_from_mask is successful. The patch adds corresponding check and return values. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/pinctrl/pinctrl-axp209.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index a52779f33ad4..afd0b533c40a 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -316,7 +316,7 @@ static const struct pinctrl_ops axp20x_pctrl_ops = { .get_group_pins = axp20x_group_pins, }; -static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, +static int axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, unsigned int mask_len, struct axp20x_pinctrl_function *func, const struct pinctrl_pin_desc *pins) @@ -331,18 +331,22 @@ static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, func->groups = devm_kcalloc(dev, ngroups, sizeof(const char *), GFP_KERNEL); + if (!func->groups) + return -ENOMEM; group = func->groups; for_each_set_bit(bit, _cpy, mask_len) { *group = pins[bit].name; group++; } } + + return 0; } -static void axp20x_build_funcs_groups(struct platform_device *pdev) +static int axp20x_build_funcs_groups(struct platform_device *pdev) { struct axp20x_pctl *pctl = platform_get_drvdata(pdev); - int i, pin, npins = pctl->desc->npins; + int i, ret, pin, npins = pctl->desc->npins; pctl->funcs[AXP20X_FUNC_GPIO_OUT].name = "gpio_out"; pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval = AXP20X_MUX_GPIO_OUT; @@ -366,13 +370,19 @@ static void axp20x_build_funcs_groups(struct platform_device *pdev) pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name; } - axp20x_funcs_groups_from_mask(>dev, pctl->desc->ldo_mask, + ret = axp20x_funcs_groups_from_mask(>dev, pctl->desc->ldo_mask, npins, >funcs[AXP20X_FUNC_LDO], pctl->desc->pins); + if (ret) + return ret; - axp20x_funcs_groups_from_mask(>dev, pctl->desc->adc_mask, + ret = axp20x_funcs_groups_from_mask(>dev, pctl->desc->adc_mask, npins, >funcs[AXP20X_FUNC_ADC], pctl->desc->pins); + if (ret) + return ret; + + return 0; } static const struct of_device_id axp20x_pctl_match[] = { @@ -424,7 +434,11 @@ static int axp20x_pctl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pctl); - axp20x_build_funcs_groups(pdev); + ret = axp20x_build_funcs_groups(pdev); + if (ret) { + dev_err(>dev, "failed to build groups\n"); + return ret; + } pctrl_desc = devm_kzalloc(>dev, sizeof(*pctrl_desc), GFP_KERNEL); if (!pctrl_desc) -- 2.18.0
[PATCH] pinctrl: axp209: Fix NULL pointer dereference after allocation
There is no check that allocation in axp20x_funcs_groups_from_mask is successful. The patch adds corresponding check and return values. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/pinctrl/pinctrl-axp209.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index a52779f33ad4..afd0b533c40a 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -316,7 +316,7 @@ static const struct pinctrl_ops axp20x_pctrl_ops = { .get_group_pins = axp20x_group_pins, }; -static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, +static int axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, unsigned int mask_len, struct axp20x_pinctrl_function *func, const struct pinctrl_pin_desc *pins) @@ -331,18 +331,22 @@ static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, func->groups = devm_kcalloc(dev, ngroups, sizeof(const char *), GFP_KERNEL); + if (!func->groups) + return -ENOMEM; group = func->groups; for_each_set_bit(bit, _cpy, mask_len) { *group = pins[bit].name; group++; } } + + return 0; } -static void axp20x_build_funcs_groups(struct platform_device *pdev) +static int axp20x_build_funcs_groups(struct platform_device *pdev) { struct axp20x_pctl *pctl = platform_get_drvdata(pdev); - int i, pin, npins = pctl->desc->npins; + int i, ret, pin, npins = pctl->desc->npins; pctl->funcs[AXP20X_FUNC_GPIO_OUT].name = "gpio_out"; pctl->funcs[AXP20X_FUNC_GPIO_OUT].muxval = AXP20X_MUX_GPIO_OUT; @@ -366,13 +370,19 @@ static void axp20x_build_funcs_groups(struct platform_device *pdev) pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name; } - axp20x_funcs_groups_from_mask(>dev, pctl->desc->ldo_mask, + ret = axp20x_funcs_groups_from_mask(>dev, pctl->desc->ldo_mask, npins, >funcs[AXP20X_FUNC_LDO], pctl->desc->pins); + if (ret) + return ret; - axp20x_funcs_groups_from_mask(>dev, pctl->desc->adc_mask, + ret = axp20x_funcs_groups_from_mask(>dev, pctl->desc->adc_mask, npins, >funcs[AXP20X_FUNC_ADC], pctl->desc->pins); + if (ret) + return ret; + + return 0; } static const struct of_device_id axp20x_pctl_match[] = { @@ -424,7 +434,11 @@ static int axp20x_pctl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pctl); - axp20x_build_funcs_groups(pdev); + ret = axp20x_build_funcs_groups(pdev); + if (ret) { + dev_err(>dev, "failed to build groups\n"); + return ret; + } pctrl_desc = devm_kzalloc(>dev, sizeof(*pctrl_desc), GFP_KERNEL); if (!pctrl_desc) -- 2.18.0
[PATCH v2] tty: rocket: Fix possible buffer overwrite on register_PCI
If number of isa and pci boards exceed NUM_BOARDS on the path rp_init()->init_PCI()->register_PCI() then buffer overwrite occurs in register_PCI() on assign rcktpt_io_addr[i]. The patch adds check on upper bound for index of registered board in register_PCI. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: do not enable device which will not be managed by driver. Based on Alan's comment. NOTE: I can't find if there is a call of pci_disable_device(), corresponding to pci_enable_device() from register_PCI(). --- drivers/tty/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index bdd17d2aaafd..f2238dc40426 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1881,7 +1881,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) ByteIO_t UPCIRingInd = 0; if (!dev || !pci_match_id(rocket_pci_ids, dev) || - pci_enable_device(dev)) + i >= NUM_BOARDS || pci_enable_device(dev)) return 0; rcktpt_io_addr[i] = pci_resource_start(dev, 0); -- 2.18.0
[PATCH v2] tty: rocket: Fix possible buffer overwrite on register_PCI
If number of isa and pci boards exceed NUM_BOARDS on the path rp_init()->init_PCI()->register_PCI() then buffer overwrite occurs in register_PCI() on assign rcktpt_io_addr[i]. The patch adds check on upper bound for index of registered board in register_PCI. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: do not enable device which will not be managed by driver. Based on Alan's comment. NOTE: I can't find if there is a call of pci_disable_device(), corresponding to pci_enable_device() from register_PCI(). --- drivers/tty/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index bdd17d2aaafd..f2238dc40426 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1881,7 +1881,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) ByteIO_t UPCIRingInd = 0; if (!dev || !pci_match_id(rocket_pci_ids, dev) || - pci_enable_device(dev)) + i >= NUM_BOARDS || pci_enable_device(dev)) return 0; rcktpt_io_addr[i] = pci_resource_start(dev, 0); -- 2.18.0
Re: [PATCH v5] staging: rts5208: add error handling into rtsx_probe
I found that staging-next already contains my patch v3, committed by Greg Kroah-Hartman. Do I need to send a new patch with a label renaming based on Dan Carpenter comments? -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru On 01.08.2018 15:18, Andy Shevchenko wrote: On Wed, Aug 1, 2018 at 2:55 PM, Anton Vasilyev wrote: If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds an error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Have you based your change on staging-next? Seems not. You need to rebase and resend.
Re: [PATCH v5] staging: rts5208: add error handling into rtsx_probe
I found that staging-next already contains my patch v3, committed by Greg Kroah-Hartman. Do I need to send a new patch with a label renaming based on Dan Carpenter comments? -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru On 01.08.2018 15:18, Andy Shevchenko wrote: On Wed, Aug 1, 2018 at 2:55 PM, Anton Vasilyev wrote: If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds an error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Have you based your change on staging-next? Seems not. You need to rebase and resend.
[PATCH v5] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds an error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v5: fix mistype and remove superfluous pointers zeroing v4: rename labels baced on Dan Carpenter's recommendation v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 32 ++-- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..6a5c670634b1 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto err_chip_free; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto err_addr_unmap; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto err_disable_msi; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto err_rtsx_release; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto err_complete_control_thread; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } dev->polling_thread = th; @@ -970,9 +968,23 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ +err_stop_host: + quiesce_and_remove_host(dev); +err_complete_control_thread: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +err_rtsx_release: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +err_disable_msi: + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +err_addr_unmap: + iounmap(dev->remap_addr); +err_chip_free: + kfree(dev->chip); errout: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.18.0
[PATCH v5] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds an error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v5: fix mistype and remove superfluous pointers zeroing v4: rename labels baced on Dan Carpenter's recommendation v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 32 ++-- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..6a5c670634b1 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto err_chip_free; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto err_addr_unmap; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto err_disable_msi; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto err_rtsx_release; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto err_complete_control_thread; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } dev->polling_thread = th; @@ -970,9 +968,23 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ +err_stop_host: + quiesce_and_remove_host(dev); +err_complete_control_thread: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +err_rtsx_release: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +err_disable_msi: + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +err_addr_unmap: + iounmap(dev->remap_addr); +err_chip_free: + kfree(dev->chip); errout: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.18.0
[PATCH v2] HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. The patch replaces kzalloc allocation by devm_kzalloc and removes ishtp_device *dev deallocation by kfree. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Acked-by: Srinivas Pandruvada --- v2: Fix align for multi line statements --- drivers/hid/intel-ish-hid/ipc/ipc.c | 9 ++--- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 -- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 9a60ec13cb10..bfbca7ec54ce 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -907,8 +907,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) struct ishtp_device *dev; int i; - dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw), - GFP_KERNEL); + dev = devm_kzalloc(>dev, + sizeof(struct ishtp_device) + sizeof(struct ish_hw), + GFP_KERNEL); if (!dev) return NULL; @@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { struct wr_msg_ctl_info *tx_buf; - tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL); + tx_buf = devm_kzalloc(>dev, + sizeof(struct wr_msg_ctl_info), + GFP_KERNEL); if (!tx_buf) { /* * IPC buffers may be limited or not available diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index a2c53ea3b5ed..81d035a480bc 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -172,7 +172,6 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) free_irq(pdev->irq, dev); free_device: pci_iounmap(pdev, hw->mem_addr); - kfree(dev); release_regions: pci_release_regions(pdev); disable_device: @@ -202,7 +201,6 @@ static void ish_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_clear_master(pdev); pci_disable_device(pdev); - kfree(ishtp_dev); } static struct device __maybe_unused *ish_resume_device; -- 2.18.0
[PATCH v2] HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. The patch replaces kzalloc allocation by devm_kzalloc and removes ishtp_device *dev deallocation by kfree. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Acked-by: Srinivas Pandruvada --- v2: Fix align for multi line statements --- drivers/hid/intel-ish-hid/ipc/ipc.c | 9 ++--- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 -- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 9a60ec13cb10..bfbca7ec54ce 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -907,8 +907,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) struct ishtp_device *dev; int i; - dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw), - GFP_KERNEL); + dev = devm_kzalloc(>dev, + sizeof(struct ishtp_device) + sizeof(struct ish_hw), + GFP_KERNEL); if (!dev) return NULL; @@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { struct wr_msg_ctl_info *tx_buf; - tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL); + tx_buf = devm_kzalloc(>dev, + sizeof(struct wr_msg_ctl_info), + GFP_KERNEL); if (!tx_buf) { /* * IPC buffers may be limited or not available diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index a2c53ea3b5ed..81d035a480bc 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -172,7 +172,6 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) free_irq(pdev->irq, dev); free_device: pci_iounmap(pdev, hw->mem_addr); - kfree(dev); release_regions: pci_release_regions(pdev); disable_device: @@ -202,7 +201,6 @@ static void ish_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_clear_master(pdev); pci_disable_device(pdev); - kfree(ishtp_dev); } static struct device __maybe_unused *ish_resume_device; -- 2.18.0
[PATCH] misc: ti-st: Fix memory leak in the error path of probe()
Free resources instead of direct return of the error code if kim_probe fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/misc/ti-st/st_kim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 5ec3f5a43718..14a5e9da32bd 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -756,14 +756,14 @@ static int kim_probe(struct platform_device *pdev) err = gpio_request(kim_gdata->nshutdown, "kim"); if (unlikely(err)) { pr_err(" gpio %d request failed ", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* Configure nShutdown GPIO as output=0 */ err = gpio_direction_output(kim_gdata->nshutdown, 0); if (unlikely(err)) { pr_err(" unable to configure gpio %d", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* get reference of pdev for request_firmware */ -- 2.18.0
[PATCH] misc: ti-st: Fix memory leak in the error path of probe()
Free resources instead of direct return of the error code if kim_probe fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/misc/ti-st/st_kim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 5ec3f5a43718..14a5e9da32bd 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -756,14 +756,14 @@ static int kim_probe(struct platform_device *pdev) err = gpio_request(kim_gdata->nshutdown, "kim"); if (unlikely(err)) { pr_err(" gpio %d request failed ", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* Configure nShutdown GPIO as output=0 */ err = gpio_direction_output(kim_gdata->nshutdown, 0); if (unlikely(err)) { pr_err(" unable to configure gpio %d", kim_gdata->nshutdown); - return err; + goto err_sysfs_group; } /* get reference of pdev for request_firmware */ -- 2.18.0
[PATCH] fmc: Fix memory leak and NULL pointer dereference
There is no deallocation of fmc memory, allocated at ff_dev_create() by kmemdup(), and no check on kmemdup() success. The patch adds deallocation into ff_dev_release() and adds check on allocation success. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/fmc/fmc-fakedev.c | 17 + 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/fmc/fmc-fakedev.c b/drivers/fmc/fmc-fakedev.c index 941d0930969a..ede589f4e8e5 100644 --- a/drivers/fmc/fmc-fakedev.c +++ b/drivers/fmc/fmc-fakedev.c @@ -244,7 +244,10 @@ static struct fmc_operations ff_fmc_operations = { /* This device is kmalloced: release it */ static void ff_dev_release(struct device *dev) { + int i; struct ff_dev *ff = container_of(dev, struct ff_dev, dev); + for (i = 0; i < ff_nr_dev; i++) + kfree(ff->fmc[i]); kfree(ff); } @@ -273,15 +276,17 @@ static struct ff_dev *ff_dev_create(void) ff->dev.release = ff_dev_release; ret = device_register(>dev); - if (ret < 0) { - put_device(>dev); - return ERR_PTR(ret); - } + if (ret < 0) + goto err; /* Create fmc structures that refer to this new "hw" device */ for (i = 0; i < ff_nr_dev; i++) { fmc = kmemdup(_template_fmc, sizeof(ff_template_fmc), GFP_KERNEL); + if (!fmc) { + ret = -ENOMEM; + goto err; + } fmc->hwdev = >dev; fmc->carrier_data = ff; fmc->nr_slots = ff_nr_dev; @@ -294,6 +299,10 @@ static struct ff_dev *ff_dev_create(void) ff_template_fmc.device_id++; } return ff; + +err: + put_device(>dev); + return ERR_PTR(ret); } /* init and exit */ -- 2.18.0
[PATCH] fmc: Fix memory leak and NULL pointer dereference
There is no deallocation of fmc memory, allocated at ff_dev_create() by kmemdup(), and no check on kmemdup() success. The patch adds deallocation into ff_dev_release() and adds check on allocation success. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/fmc/fmc-fakedev.c | 17 + 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/fmc/fmc-fakedev.c b/drivers/fmc/fmc-fakedev.c index 941d0930969a..ede589f4e8e5 100644 --- a/drivers/fmc/fmc-fakedev.c +++ b/drivers/fmc/fmc-fakedev.c @@ -244,7 +244,10 @@ static struct fmc_operations ff_fmc_operations = { /* This device is kmalloced: release it */ static void ff_dev_release(struct device *dev) { + int i; struct ff_dev *ff = container_of(dev, struct ff_dev, dev); + for (i = 0; i < ff_nr_dev; i++) + kfree(ff->fmc[i]); kfree(ff); } @@ -273,15 +276,17 @@ static struct ff_dev *ff_dev_create(void) ff->dev.release = ff_dev_release; ret = device_register(>dev); - if (ret < 0) { - put_device(>dev); - return ERR_PTR(ret); - } + if (ret < 0) + goto err; /* Create fmc structures that refer to this new "hw" device */ for (i = 0; i < ff_nr_dev; i++) { fmc = kmemdup(_template_fmc, sizeof(ff_template_fmc), GFP_KERNEL); + if (!fmc) { + ret = -ENOMEM; + goto err; + } fmc->hwdev = >dev; fmc->carrier_data = ff; fmc->nr_slots = ff_nr_dev; @@ -294,6 +299,10 @@ static struct ff_dev *ff_dev_create(void) ff_template_fmc.device_id++; } return ff; + +err: + put_device(>dev); + return ERR_PTR(ret); } /* init and exit */ -- 2.18.0
[PATCH] regulator: tps65217: Fix NULL pointer dereference on probe
There is no check that tps->strobes is allocated successfully in tps65217_regulator_probe(). The patch adds corresponding check. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/regulator/tps65217-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index fc12badf3805..d84fab616abf 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -232,6 +232,8 @@ static int tps65217_regulator_probe(struct platform_device *pdev) tps->strobes = devm_kcalloc(>dev, TPS65217_NUM_REGULATOR, sizeof(u8), GFP_KERNEL); + if (!tps->strobes) + return -ENOMEM; platform_set_drvdata(pdev, tps); -- 2.18.0
[PATCH] regulator: tps65217: Fix NULL pointer dereference on probe
There is no check that tps->strobes is allocated successfully in tps65217_regulator_probe(). The patch adds corresponding check. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/regulator/tps65217-regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index fc12badf3805..d84fab616abf 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -232,6 +232,8 @@ static int tps65217_regulator_probe(struct platform_device *pdev) tps->strobes = devm_kcalloc(>dev, TPS65217_NUM_REGULATOR, sizeof(u8), GFP_KERNEL); + if (!tps->strobes) + return -ENOMEM; platform_set_drvdata(pdev, tps); -- 2.18.0
[PATCH] tty: rocket: Fix possible buffer overwrite on register_PCI
If number of isa and pci boards exceed NUM_BOARDS on the path rp_init()->init_PCI()->register_PCI() then buffer overwrite occurs in register_PCI() on assign rcktpt_io_addr[i]. The patch adds check on upper bound for index of registered board in register_PCI. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/tty/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index bdd17d2aaafd..b121d8f8f3d7 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1881,7 +1881,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) ByteIO_t UPCIRingInd = 0; if (!dev || !pci_match_id(rocket_pci_ids, dev) || - pci_enable_device(dev)) + pci_enable_device(dev) || i >= NUM_BOARDS) return 0; rcktpt_io_addr[i] = pci_resource_start(dev, 0); -- 2.18.0
[PATCH] tty: rocket: Fix possible buffer overwrite on register_PCI
If number of isa and pci boards exceed NUM_BOARDS on the path rp_init()->init_PCI()->register_PCI() then buffer overwrite occurs in register_PCI() on assign rcktpt_io_addr[i]. The patch adds check on upper bound for index of registered board in register_PCI. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/tty/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index bdd17d2aaafd..b121d8f8f3d7 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1881,7 +1881,7 @@ static __init int register_PCI(int i, struct pci_dev *dev) ByteIO_t UPCIRingInd = 0; if (!dev || !pci_match_id(rocket_pci_ids, dev) || - pci_enable_device(dev)) + pci_enable_device(dev) || i >= NUM_BOARDS) return 0; rcktpt_io_addr[i] = pci_resource_start(dev, 0); -- 2.18.0
[PATCH] media: davinci: vpif_display: Mix memory leak on probe error path
If vpif_probe() fails on v4l2_device_register() then memory allocated at initialize_vpif() for global vpif_obj.dev[i] become unreleased. The patch adds deallocation of vpif_obj.dev[i] on the error path and removes duplicated check on platform_data presence. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/media/platform/davinci/vpif_display.c | 24 --- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 7be636237acf..0f324055cc9f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1114,6 +1114,14 @@ static int initialize_vpif(void) return err; } +static void free_vpif_objs(void) +{ + int i; + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) + kfree(vpif_obj.dev[i]); +} + static int vpif_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) @@ -1255,11 +1263,6 @@ static __init int vpif_probe(struct platform_device *pdev) return -EINVAL; } - if (!pdev->dev.platform_data) { - dev_warn(>dev, "Missing platform data. Giving up.\n"); - return -EINVAL; - } - vpif_dev = >dev; err = initialize_vpif(); @@ -1271,7 +1274,7 @@ static __init int vpif_probe(struct platform_device *pdev) err = v4l2_device_register(vpif_dev, _obj.v4l2_dev); if (err) { v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - return err; + goto vpif_free; } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { @@ -1314,7 +1317,10 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd[i]) vpif_obj.sd[i]->grp_id = 1 << i; } - vpif_probe_complete(); + err = vpif_probe_complete(); + if (err) { + goto probe_subdev_out; + } } else { vpif_obj.notifier.subdevs = vpif_obj.config->asd; vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; @@ -1334,6 +1340,8 @@ static __init int vpif_probe(struct platform_device *pdev) kfree(vpif_obj.sd); vpif_unregister: v4l2_device_unregister(_obj.v4l2_dev); +vpif_free: + free_vpif_objs(); return err; } @@ -1355,8 +1363,8 @@ static int vpif_remove(struct platform_device *device) ch = vpif_obj.dev[i]; /* Unregister video device */ video_unregister_device(>video_dev); - kfree(vpif_obj.dev[i]); } + free_vpif_objs(); return 0; } -- 2.18.0
[PATCH] media: davinci: vpif_display: Mix memory leak on probe error path
If vpif_probe() fails on v4l2_device_register() then memory allocated at initialize_vpif() for global vpif_obj.dev[i] become unreleased. The patch adds deallocation of vpif_obj.dev[i] on the error path and removes duplicated check on platform_data presence. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/media/platform/davinci/vpif_display.c | 24 --- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 7be636237acf..0f324055cc9f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1114,6 +1114,14 @@ static int initialize_vpif(void) return err; } +static void free_vpif_objs(void) +{ + int i; + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) + kfree(vpif_obj.dev[i]); +} + static int vpif_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) @@ -1255,11 +1263,6 @@ static __init int vpif_probe(struct platform_device *pdev) return -EINVAL; } - if (!pdev->dev.platform_data) { - dev_warn(>dev, "Missing platform data. Giving up.\n"); - return -EINVAL; - } - vpif_dev = >dev; err = initialize_vpif(); @@ -1271,7 +1274,7 @@ static __init int vpif_probe(struct platform_device *pdev) err = v4l2_device_register(vpif_dev, _obj.v4l2_dev); if (err) { v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - return err; + goto vpif_free; } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { @@ -1314,7 +1317,10 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd[i]) vpif_obj.sd[i]->grp_id = 1 << i; } - vpif_probe_complete(); + err = vpif_probe_complete(); + if (err) { + goto probe_subdev_out; + } } else { vpif_obj.notifier.subdevs = vpif_obj.config->asd; vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; @@ -1334,6 +1340,8 @@ static __init int vpif_probe(struct platform_device *pdev) kfree(vpif_obj.sd); vpif_unregister: v4l2_device_unregister(_obj.v4l2_dev); +vpif_free: + free_vpif_objs(); return err; } @@ -1355,8 +1363,8 @@ static int vpif_remove(struct platform_device *device) ch = vpif_obj.dev[i]; /* Unregister video device */ video_unregister_device(>video_dev); - kfree(vpif_obj.dev[i]); } + free_vpif_objs(); return 0; } -- 2.18.0
[PATCH v2] firmware: vpd: Fix section enabled flag on vpd_section_destroy
static struct ro_vpd and rw_vpd are initialized by vpd_sections_init() in vpd_probe() based on header's ro and rw sizes. In vpd_remove() vpd_section_destroy() performs deinitialization based on enabled flag, which is set to true by vpd_sections_init(). This leads to call of vpd_section_destroy() on already destroyed section for probe-release-probe-release sequence if first probe performs ro_vpd initialization and second probe does not initialize it. The patch adds changing enabled flag on vpd_section_destroy and adds cleanup on the error path of vpd_sections_init. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: add cleanup on the error path of vpd_sections_init --- drivers/firmware/google/vpd.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index e9db895916c3..1aa67bb5d8c0 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec) sysfs_remove_bin_file(vpd_kobj, >bin_attr); kfree(sec->raw_name); memunmap(sec->baseaddr); + sec->enabled = false; } return 0; @@ -279,8 +280,10 @@ static int vpd_sections_init(phys_addr_t physaddr) ret = vpd_section_init("rw", _vpd, physaddr + sizeof(struct vpd_cbmem) + header.ro_size, header.rw_size); - if (ret) + if (ret) { + vpd_section_destroy(_vpd); return ret; + } } return 0; -- 2.18.0
[PATCH v2] firmware: vpd: Fix section enabled flag on vpd_section_destroy
static struct ro_vpd and rw_vpd are initialized by vpd_sections_init() in vpd_probe() based on header's ro and rw sizes. In vpd_remove() vpd_section_destroy() performs deinitialization based on enabled flag, which is set to true by vpd_sections_init(). This leads to call of vpd_section_destroy() on already destroyed section for probe-release-probe-release sequence if first probe performs ro_vpd initialization and second probe does not initialize it. The patch adds changing enabled flag on vpd_section_destroy and adds cleanup on the error path of vpd_sections_init. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: add cleanup on the error path of vpd_sections_init --- drivers/firmware/google/vpd.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index e9db895916c3..1aa67bb5d8c0 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec) sysfs_remove_bin_file(vpd_kobj, >bin_attr); kfree(sec->raw_name); memunmap(sec->baseaddr); + sec->enabled = false; } return 0; @@ -279,8 +280,10 @@ static int vpd_sections_init(phys_addr_t physaddr) ret = vpd_section_init("rw", _vpd, physaddr + sizeof(struct vpd_cbmem) + header.ro_size, header.rw_size); - if (ret) + if (ret) { + vpd_section_destroy(_vpd); return ret; + } } return 0; -- 2.18.0
[PATCH] HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. The patch replaces kzalloc allocation by devm_kzalloc and removes ishtp_device *dev deallocation by kfree. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/hid/intel-ish-hid/ipc/ipc.c | 7 +-- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 9a60ec13cb10..2f8e5402b450 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -907,7 +907,8 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) struct ishtp_device *dev; int i; - dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw), + dev = devm_kzalloc(>dev, + sizeof(struct ishtp_device) + sizeof(struct ish_hw), GFP_KERNEL); if (!dev) return NULL; @@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { struct wr_msg_ctl_info *tx_buf; - tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL); + tx_buf = devm_kzalloc(>dev, + sizeof(struct wr_msg_ctl_info), + GFP_KERNEL); if (!tx_buf) { /* * IPC buffers may be limited or not available diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index a2c53ea3b5ed..81d035a480bc 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -172,7 +172,6 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) free_irq(pdev->irq, dev); free_device: pci_iounmap(pdev, hw->mem_addr); - kfree(dev); release_regions: pci_release_regions(pdev); disable_device: @@ -202,7 +201,6 @@ static void ish_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_clear_master(pdev); pci_disable_device(pdev); - kfree(ishtp_dev); } static struct device __maybe_unused *ish_resume_device; -- 2.18.0
[PATCH] HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. The patch replaces kzalloc allocation by devm_kzalloc and removes ishtp_device *dev deallocation by kfree. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/hid/intel-ish-hid/ipc/ipc.c | 7 +-- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 9a60ec13cb10..2f8e5402b450 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -907,7 +907,8 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) struct ishtp_device *dev; int i; - dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw), + dev = devm_kzalloc(>dev, + sizeof(struct ishtp_device) + sizeof(struct ish_hw), GFP_KERNEL); if (!dev) return NULL; @@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { struct wr_msg_ctl_info *tx_buf; - tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL); + tx_buf = devm_kzalloc(>dev, + sizeof(struct wr_msg_ctl_info), + GFP_KERNEL); if (!tx_buf) { /* * IPC buffers may be limited or not available diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index a2c53ea3b5ed..81d035a480bc 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -172,7 +172,6 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) free_irq(pdev->irq, dev); free_device: pci_iounmap(pdev, hw->mem_addr); - kfree(dev); release_regions: pci_release_regions(pdev); disable_device: @@ -202,7 +201,6 @@ static void ish_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_clear_master(pdev); pci_disable_device(pdev); - kfree(ishtp_dev); } static struct device __maybe_unused *ish_resume_device; -- 2.18.0
HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. I have two ideas 1) to replace kzalloc allocation by devm_kzalloc, or 2) release memory stored at >wr_free_list_head.link list (and may be at >wr_processing_list_head.link) in all driver exits. But I do not know which way is preferable for this case. Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
HID: intel_ish-hid: tx_buf memory leak on probe/remove
ish_dev_init() allocates 512*176 bytes memory for tx_buf and stores it at >wr_free_list_head.link list on ish_probe(). But there is no deallocation of this memory in ish_remove() and in ish_probe() error path. So current intel-ish-ipc provides 88 KB memory leak for each probe/release. I have two ideas 1) to replace kzalloc allocation by devm_kzalloc, or 2) release memory stored at >wr_free_list_head.link list (and may be at >wr_processing_list_head.link) in all driver exits. But I do not know which way is preferable for this case. Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
[PATCH] gpio: ml-ioh: Fix buffer underwrite on probe error path
If ioh_gpio_probe() fails on devm_irq_alloc_descs() then chip may point to any element of chip_save array, so reverse iteration from pointer chip may become chip_save[-1] and gpiochip_remove() will operate with wrong memory. The patch fix the error path of ioh_gpio_probe() to correctly bypass chip_save array. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/gpio/gpio-ml-ioh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index b23d9a36be1f..51c7d1b84c2e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -496,9 +496,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev, return 0; err_gpiochip_add: + chip = chip_save; while (--i >= 0) { - chip--; gpiochip_remove(>gpio); + chip++; } kfree(chip_save); -- 2.18.0
[PATCH] gpio: ml-ioh: Fix buffer underwrite on probe error path
If ioh_gpio_probe() fails on devm_irq_alloc_descs() then chip may point to any element of chip_save array, so reverse iteration from pointer chip may become chip_save[-1] and gpiochip_remove() will operate with wrong memory. The patch fix the error path of ioh_gpio_probe() to correctly bypass chip_save array. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/gpio/gpio-ml-ioh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index b23d9a36be1f..51c7d1b84c2e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -496,9 +496,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev, return 0; err_gpiochip_add: + chip = chip_save; while (--i >= 0) { - chip--; gpiochip_remove(>gpio); + chip++; } kfree(chip_save); -- 2.18.0
[PATCH] firmware: vpd: Fix section enabled flag on vpd_section_destroy
static struct ro_vpd and rw_vpd are initialized by vpd_sections_init() in vpd_probe() based on header's ro and rw sizes. In vpd_remove() vpd_section_destroy() performs deinitialization based on enabled flag, which is set to true by vpd_sections_init(). This leads to call of vpd_section_destroy() on already destroyed section for probe-release-probe-release sequence if first probe performs ro_vpd initialization and second probe does not initialize it. The patch adds changing enabled flag on vpd_section_destroy. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/firmware/google/vpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index e9db895916c3..5347c17c7108 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec) sysfs_remove_bin_file(vpd_kobj, >bin_attr); kfree(sec->raw_name); memunmap(sec->baseaddr); + sec->enabled = false; } return 0; -- 2.18.0
[PATCH] firmware: vpd: Fix section enabled flag on vpd_section_destroy
static struct ro_vpd and rw_vpd are initialized by vpd_sections_init() in vpd_probe() based on header's ro and rw sizes. In vpd_remove() vpd_section_destroy() performs deinitialization based on enabled flag, which is set to true by vpd_sections_init(). This leads to call of vpd_section_destroy() on already destroyed section for probe-release-probe-release sequence if first probe performs ro_vpd initialization and second probe does not initialize it. The patch adds changing enabled flag on vpd_section_destroy. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/firmware/google/vpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index e9db895916c3..5347c17c7108 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec) sysfs_remove_bin_file(vpd_kobj, >bin_attr); kfree(sec->raw_name); memunmap(sec->baseaddr); + sec->enabled = false; } return 0; -- 2.18.0
[PATCH] uwb: hwa-rc: fix memory leak at probe
hwarc_probe() allocates memory for hwarc, but does not free it if uwb_rc_add() or hwarc_get_version() fail. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/uwb/hwa-rc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 9a53912bdfe9..5d3ba747ae17 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -873,6 +873,7 @@ static int hwarc_probe(struct usb_interface *iface, error_rc_add: usb_put_intf(iface); usb_put_dev(hwarc->usb_dev); + kfree(hwarc); error_alloc: uwb_rc_put(uwb_rc); error_rc_alloc: -- 2.18.0
[PATCH] uwb: hwa-rc: fix memory leak at probe
hwarc_probe() allocates memory for hwarc, but does not free it if uwb_rc_add() or hwarc_get_version() fail. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/uwb/hwa-rc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 9a53912bdfe9..5d3ba747ae17 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -873,6 +873,7 @@ static int hwarc_probe(struct usb_interface *iface, error_rc_add: usb_put_intf(iface); usb_put_dev(hwarc->usb_dev); + kfree(hwarc); error_alloc: uwb_rc_put(uwb_rc); error_rc_alloc: -- 2.18.0
[PATCH v4] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v4: rename labels baced on Dan Carpenter's recommendation v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 34 -- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..233026ee5dd4 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto err_chip_free; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto err_addr_unmap; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto err_disable_msi; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto err_rtsx_release; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto err_complete_control_thread; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ +err_stop_host: + quiesce_and_remove_host(dev); +err_complete_control_thread: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +err_rtsx_release: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +err_disable_msi: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +err_addr_unmap: + iounmap(dev->remap_addr); +err_chip_free: + kfree(dev->chip); errout: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH v4] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v4: rename labels baced on Dan Carpenter's recommendation v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 34 -- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..233026ee5dd4 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto err_chip_free; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto err_addr_unmap; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto err_disable_msi; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto err_rtsx_release; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto err_complete_control_thread; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto err_stop_host; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ +err_stop_host: + quiesce_and_remove_host(dev); +err_complete_control_thread: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +err_rtsx_release: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +err_disable_msi: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +err_addr_unmap: + iounmap(dev->remap_addr); +err_chip_free: + kfree(dev->chip); errout: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH v3] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH v3] staging: rts5208: add error handling into rtsx_probe
If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[no subject]
Subject: [PATCH v3] staging: rts5208: add error handling into rtsx_probe If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[no subject]
Subject: [PATCH v3] staging: rts5208: add error handling into rtsx_probe If rtsx_probe() fails to allocate dev->chip, then release_everything() will crash on uninitialized dev->cmnd_ready complete. Patch adds error handling into rtsx_probe. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v3: fix subject and commit message v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH v2] staging: rts5208: add check on NULL before dereference
If rtsx_probe() fails to allocate dev->chip, then NULL pointer dereference occurs at release_everything()->rtsx_release_resources(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH v2] staging: rts5208: add check on NULL before dereference
If rtsx_probe() fails to allocate dev->chip, then NULL pointer dereference occurs at release_everything()->rtsx_release_resources(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Add error handling into rtsx_probe based on Dan Carpenter's comment. I do not have corresponding hardware, so patch was tested by compilation only. I faced with inaccuracy at rtsx_remove() and original rtsx_probe(): there is quiesce_and_remove_host() call with scsi_remove_host() inside, whereas release_everything() calls scsi_host_put() after this scsi_remove_host() call. This is strange for me. Also I do not know is it require to check result value of rtsx_init_chip() call on rtsx_probe(). --- drivers/staging/rts5208/rtsx.c | 38 +++--- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..69e6abe14abf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -857,7 +857,7 @@ static int rtsx_probe(struct pci_dev *pci, dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); if (!dev->chip) { err = -ENOMEM; - goto errout; + goto chip_alloc_fail; } spin_lock_init(>reg_lock); @@ -879,7 +879,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->remap_addr) { dev_err(>dev, "ioremap error\n"); err = -ENXIO; - goto errout; + goto ioremap_fail; } /* @@ -894,7 +894,7 @@ static int rtsx_probe(struct pci_dev *pci, if (!dev->rtsx_resv_buf) { dev_err(>dev, "alloc dma buffer fail\n"); err = -ENXIO; - goto errout; + goto dma_alloc_fail; } dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; @@ -915,7 +915,7 @@ static int rtsx_probe(struct pci_dev *pci, if (rtsx_acquire_irq(dev) < 0) { err = -EBUSY; - goto errout; + goto irq_acquire_fail; } pci_set_master(pci); @@ -935,14 +935,14 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start control thread\n"); err = PTR_ERR(th); - goto errout; + goto control_thread_fail; } dev->ctl_thread = th; err = scsi_add_host(host, >dev); if (err) { dev_err(>dev, "Unable to add the scsi host\n"); - goto errout; + goto scsi_add_host_fail; } /* Start up the thread for delayed SCSI-device scanning */ @@ -950,18 +950,16 @@ static int rtsx_probe(struct pci_dev *pci, if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-scanning thread\n"); complete(>scanning_done); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } /* Start up the thread for polling thread */ th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); if (IS_ERR(th)) { dev_err(>dev, "Unable to start the device-polling thread\n"); - quiesce_and_remove_host(dev); err = PTR_ERR(th); - goto errout; + goto scan_thread_fail; } dev->polling_thread = th; @@ -970,9 +968,25 @@ static int rtsx_probe(struct pci_dev *pci, return 0; /* We come here if there are any problems */ -errout: +scan_thread_fail: + quiesce_and_remove_host(dev); +scsi_add_host_fail: + complete(>cmnd_ready); + wait_for_completion(>control_exit); +control_thread_fail: + free_irq(dev->irq, (void *)dev); + rtsx_release_chip(dev->chip); +irq_acquire_fail: + dev->chip->host_cmds_ptr = NULL; + dev->chip->host_sg_tbl_ptr = NULL; + if (dev->chip->msi_en) + pci_disable_msi(dev->pci); +dma_alloc_fail: + iounmap(dev->remap_addr); +ioremap_fail: + kfree(dev->chip); +chip_alloc_fail: dev_err(>dev, "%s failed\n", __func__); - release_everything(dev); return err; } -- 2.17.1
[PATCH] staging: rts5208: add check on NULL before dereference
If rtsx_probe fails to allocate dev->chip, then NULL pointer dereference occurs at rtsx_release_resources(). Patch adds checks chip on NULL before its dereference at rtsx_release_resources and passing with dereference inside rtsx_release_chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/staging/rts5208/rtsx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..952dd0d580cf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -623,12 +623,13 @@ static void rtsx_release_resources(struct rtsx_dev *dev) if (dev->irq > 0) free_irq(dev->irq, (void *)dev); - if (dev->chip->msi_en) + if (dev->chip && dev->chip->msi_en) pci_disable_msi(dev->pci); if (dev->remap_addr) iounmap(dev->remap_addr); + if (dev->chip) + rtsx_release_chip(dev->chip); - rtsx_release_chip(dev->chip); kfree(dev->chip); } -- 2.17.1
[PATCH] staging: rts5208: add check on NULL before dereference
If rtsx_probe fails to allocate dev->chip, then NULL pointer dereference occurs at rtsx_release_resources(). Patch adds checks chip on NULL before its dereference at rtsx_release_resources and passing with dereference inside rtsx_release_chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/staging/rts5208/rtsx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 70e0b8623110..952dd0d580cf 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -623,12 +623,13 @@ static void rtsx_release_resources(struct rtsx_dev *dev) if (dev->irq > 0) free_irq(dev->irq, (void *)dev); - if (dev->chip->msi_en) + if (dev->chip && dev->chip->msi_en) pci_disable_msi(dev->pci); if (dev->remap_addr) iounmap(dev->remap_addr); + if (dev->chip) + rtsx_release_chip(dev->chip); - rtsx_release_chip(dev->chip); kfree(dev->chip); } -- 2.17.1
Re: [PATCH] udc: Memory leak on error path and use after free
Sorry for delayed reply. On 16.08.2017 19:35, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: On 16.08.2017 18:29, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. This isn't needed if usb_add_gadget_udc_release() is fixed, right? No, this situation could appear before call usb_add_gadget_udc_release(). Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. Where is there a possible use after free? net2280_remove() continue work with struct net2280 *dev after call usb_del_gadget_udc(>gadget), but this net2280 *dev could be deallocated by gadget_release() The patch moves deallocation from gadget_release() to net2280_remove(). Alan Stern Okay, now I understand what you were saying. Yes, I agree, the existing code isn't right. But a better solution would be to move the usb_del_gadget_udc() call from the beginning of net2280_remove() to the end. And make the call conditional, depending on whether usb_add_gadget_udc_release() has already been called successfully. If allow gadget_release() to deallocate net2280 *dev then it will be called on fail of usb_add_gadget_udc_release() and it will be unsafe to perform clean-up. My point is that gadget shouldn't deallocate its parent memory at all. The point is that the device core does not allow drivers to deallocate memory containing a struct device before the ->release callback has been invoked. Your patch might do that, if the release was delayed for some reason. I don't see possibility for parent device to be removed before its child was released. Please point if I'm wrong. Alternative way to move allocation under devm interface. Alan Stern -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
Re: [PATCH] udc: Memory leak on error path and use after free
Sorry for delayed reply. On 16.08.2017 19:35, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: On 16.08.2017 18:29, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. This isn't needed if usb_add_gadget_udc_release() is fixed, right? No, this situation could appear before call usb_add_gadget_udc_release(). Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. Where is there a possible use after free? net2280_remove() continue work with struct net2280 *dev after call usb_del_gadget_udc(>gadget), but this net2280 *dev could be deallocated by gadget_release() The patch moves deallocation from gadget_release() to net2280_remove(). Alan Stern Okay, now I understand what you were saying. Yes, I agree, the existing code isn't right. But a better solution would be to move the usb_del_gadget_udc() call from the beginning of net2280_remove() to the end. And make the call conditional, depending on whether usb_add_gadget_udc_release() has already been called successfully. If allow gadget_release() to deallocate net2280 *dev then it will be called on fail of usb_add_gadget_udc_release() and it will be unsafe to perform clean-up. My point is that gadget shouldn't deallocate its parent memory at all. The point is that the device core does not allow drivers to deallocate memory containing a struct device before the ->release callback has been invoked. Your patch might do that, if the release was delayed for some reason. I don't see possibility for parent device to be removed before its child was released. Please point if I'm wrong. Alternative way to move allocation under devm interface. Alan Stern -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
[PATCH v3] mtd: plat-ram: Replace manual resource management by devm
Driver contains unsuitable request_mem_region() and release_resource() calls. The patch switches manual resource management by devm interface for readability and error-free simplification. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> Suggested-by: Boris Brezillon <boris.brezil...@free-electrons.com> --- v1: Fix commit based on Boris Brezillon review --- v2: Change commit by Boris Brezillon solution --- v3: Change description with title --- drivers/mtd/maps/plat-ram.c | 38 -- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..6d9a4d6 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -43,7 +43,6 @@ struct platram_info { struct device *dev; struct mtd_info *mtd; struct map_info map; - struct resource *area; struct platdata_mtd_ram *pdata; }; @@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev) platram_setrw(info, PLATRAM_RO); - /* release resources */ - - if (info->area) { - release_resource(info->area); - kfree(info->area); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - kfree(info); return 0; @@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev) info->pdata = pdata; /* get the resource for the memory mapping */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - dev_err(>dev, "no memory resource specified\n"); - err = -ENOENT; + info->map.virt = devm_ioremap_resource(>dev, res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + dev_err(>dev, "failed to ioremap() region\n"); goto exit_free; } @@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev) (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; - /* register our usage of the memory area */ - - info->area = request_mem_region(res->start, info->map.size, pdev->name); - if (info->area == NULL) { - dev_err(>dev, "failed to request memory region\n"); - err = -EIO; - goto exit_free; - } - - /* remap the memory area */ - - info->map.virt = ioremap(res->start, info->map.size); dev_dbg(>dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); - if (info->map.virt == NULL) { - dev_err(>dev, "failed to ioremap() region\n"); - err = -EIO; - goto exit_free; - } - simple_map_init(>map); dev_dbg(>dev, "initialised map, probing for mtd\n"); -- 2.7.4
[PATCH v3] mtd: plat-ram: Replace manual resource management by devm
Driver contains unsuitable request_mem_region() and release_resource() calls. The patch switches manual resource management by devm interface for readability and error-free simplification. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Suggested-by: Boris Brezillon --- v1: Fix commit based on Boris Brezillon review --- v2: Change commit by Boris Brezillon solution --- v3: Change description with title --- drivers/mtd/maps/plat-ram.c | 38 -- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..6d9a4d6 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -43,7 +43,6 @@ struct platram_info { struct device *dev; struct mtd_info *mtd; struct map_info map; - struct resource *area; struct platdata_mtd_ram *pdata; }; @@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev) platram_setrw(info, PLATRAM_RO); - /* release resources */ - - if (info->area) { - release_resource(info->area); - kfree(info->area); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - kfree(info); return 0; @@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev) info->pdata = pdata; /* get the resource for the memory mapping */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - dev_err(>dev, "no memory resource specified\n"); - err = -ENOENT; + info->map.virt = devm_ioremap_resource(>dev, res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + dev_err(>dev, "failed to ioremap() region\n"); goto exit_free; } @@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev) (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; - /* register our usage of the memory area */ - - info->area = request_mem_region(res->start, info->map.size, pdev->name); - if (info->area == NULL) { - dev_err(>dev, "failed to request memory region\n"); - err = -EIO; - goto exit_free; - } - - /* remap the memory area */ - - info->map.virt = ioremap(res->start, info->map.size); dev_dbg(>dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); - if (info->map.virt == NULL) { - dev_err(>dev, "failed to ioremap() region\n"); - err = -EIO; - goto exit_free; - } - simple_map_init(>map); dev_dbg(>dev, "initialised map, probing for mtd\n"); -- 2.7.4
[PATCH v2] mtd: plat-ram: use release_mem_region instead of release_resource
Replace ioremap() and request_mem_region() by devm_ioremap_resource(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> Suggested-by: Boris Brezillon <boris.brezil...@free-electrons.com> --- v1: Fix commit based on Boris Brezillon review --- v2: Change commit by Boris Brezillon solution --- drivers/mtd/maps/plat-ram.c | 38 -- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..6d9a4d6 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -43,7 +43,6 @@ struct platram_info { struct device *dev; struct mtd_info *mtd; struct map_info map; - struct resource *area; struct platdata_mtd_ram *pdata; }; @@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev) platram_setrw(info, PLATRAM_RO); - /* release resources */ - - if (info->area) { - release_resource(info->area); - kfree(info->area); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - kfree(info); return 0; @@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev) info->pdata = pdata; /* get the resource for the memory mapping */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - dev_err(>dev, "no memory resource specified\n"); - err = -ENOENT; + info->map.virt = devm_ioremap_resource(>dev, res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + dev_err(>dev, "failed to ioremap() region\n"); goto exit_free; } @@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev) (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; - /* register our usage of the memory area */ - - info->area = request_mem_region(res->start, info->map.size, pdev->name); - if (info->area == NULL) { - dev_err(>dev, "failed to request memory region\n"); - err = -EIO; - goto exit_free; - } - - /* remap the memory area */ - - info->map.virt = ioremap(res->start, info->map.size); dev_dbg(>dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); - if (info->map.virt == NULL) { - dev_err(>dev, "failed to ioremap() region\n"); - err = -EIO; - goto exit_free; - } - simple_map_init(>map); dev_dbg(>dev, "initialised map, probing for mtd\n"); -- 2.7.4
[PATCH v2] mtd: plat-ram: use release_mem_region instead of release_resource
Replace ioremap() and request_mem_region() by devm_ioremap_resource(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Suggested-by: Boris Brezillon --- v1: Fix commit based on Boris Brezillon review --- v2: Change commit by Boris Brezillon solution --- drivers/mtd/maps/plat-ram.c | 38 -- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..6d9a4d6 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -43,7 +43,6 @@ struct platram_info { struct device *dev; struct mtd_info *mtd; struct map_info map; - struct resource *area; struct platdata_mtd_ram *pdata; }; @@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev) platram_setrw(info, PLATRAM_RO); - /* release resources */ - - if (info->area) { - release_resource(info->area); - kfree(info->area); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - kfree(info); return 0; @@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev) info->pdata = pdata; /* get the resource for the memory mapping */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - dev_err(>dev, "no memory resource specified\n"); - err = -ENOENT; + info->map.virt = devm_ioremap_resource(>dev, res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + dev_err(>dev, "failed to ioremap() region\n"); goto exit_free; } @@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev) (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; - /* register our usage of the memory area */ - - info->area = request_mem_region(res->start, info->map.size, pdev->name); - if (info->area == NULL) { - dev_err(>dev, "failed to request memory region\n"); - err = -EIO; - goto exit_free; - } - - /* remap the memory area */ - - info->map.virt = ioremap(res->start, info->map.size); dev_dbg(>dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); - if (info->map.virt == NULL) { - dev_err(>dev, "failed to ioremap() region\n"); - err = -EIO; - goto exit_free; - } - simple_map_init(>map); dev_dbg(>dev, "initialised map, probing for mtd\n"); -- 2.7.4
Re: [PATCH] udc: Memory leak on error path and use after free
On 16.08.2017 18:29, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. This isn't needed if usb_add_gadget_udc_release() is fixed, right? No, this situation could appear before call usb_add_gadget_udc_release(). Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. Where is there a possible use after free? net2280_remove() continue work with struct net2280 *dev after call usb_del_gadget_udc(>gadget), but this net2280 *dev could be deallocated by gadget_release() The patch moves deallocation from gadget_release() to net2280_remove(). Alan Stern -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
Re: [PATCH] udc: Memory leak on error path and use after free
On 16.08.2017 18:29, Alan Stern wrote: On Wed, 16 Aug 2017, Anton Vasilyev wrote: gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. This isn't needed if usb_add_gadget_udc_release() is fixed, right? No, this situation could appear before call usb_add_gadget_udc_release(). Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. Where is there a possible use after free? net2280_remove() continue work with struct net2280 *dev after call usb_del_gadget_udc(>gadget), but this net2280 *dev could be deallocated by gadget_release() The patch moves deallocation from gadget_release() to net2280_remove(). Alan Stern -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
[PATCH] udc: Memory leak on error path and use after free
gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. The patch moves deallocation from gadget_release() to net2280_remove(). Found by Linux Driver Verififcation project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/usb/gadget/udc/net2280.c | 14 +++--- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index f608c1f..62ac876 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -3546,15 +3546,6 @@ static irqreturn_t net2280_irq(int irq, void *_dev) return IRQ_HANDLED; } -/*-*/ - -static void gadget_release(struct device *_dev) -{ - struct net2280 *dev = dev_get_drvdata(_dev); - - kfree(dev); -} - /* tear down the binding between this driver and the pci device */ static void net2280_remove(struct pci_dev *pdev) @@ -3592,6 +3583,8 @@ static void net2280_remove(struct pci_dev *pdev) device_remove_file(>dev, _attr_registers); ep_info(dev, "unbind\n"); + + kfree(dev); } /* wrap this driver around the specified device, but @@ -3769,8 +3762,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (retval) goto done; - retval = usb_add_gadget_udc_release(>dev, >gadget, - gadget_release); + retval = usb_add_gadget_udc(>dev, >gadget); if (retval) goto done; return 0; -- 2.7.4
[PATCH] udc: Memory leak on error path and use after free
gadget_release() is responsible for cleanup dev memory. But if net2280_probe() fails after dev allocation, then gadget_release() become unregistered and dev memory leaks. Also net2280_remove() calls usb_del_gadget_udc() which perform schedule_delayed_work() with gadget_release(), so it is possible that dev will be deallocated exactly after this call and leads to use after free. The patch moves deallocation from gadget_release() to net2280_remove(). Found by Linux Driver Verififcation project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/usb/gadget/udc/net2280.c | 14 +++--- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index f608c1f..62ac876 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -3546,15 +3546,6 @@ static irqreturn_t net2280_irq(int irq, void *_dev) return IRQ_HANDLED; } -/*-*/ - -static void gadget_release(struct device *_dev) -{ - struct net2280 *dev = dev_get_drvdata(_dev); - - kfree(dev); -} - /* tear down the binding between this driver and the pci device */ static void net2280_remove(struct pci_dev *pdev) @@ -3592,6 +3583,8 @@ static void net2280_remove(struct pci_dev *pdev) device_remove_file(>dev, _attr_registers); ep_info(dev, "unbind\n"); + + kfree(dev); } /* wrap this driver around the specified device, but @@ -3769,8 +3762,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (retval) goto done; - retval = usb_add_gadget_udc_release(>dev, >gadget, - gadget_release); + retval = usb_add_gadget_udc(>dev, >gadget); if (retval) goto done; return 0; -- 2.7.4
[PATCH v1] mtd: plat-ram: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting. Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v1: Fix commit based on Boris Brezillon review --- drivers/mtd/maps/plat-ram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..90bc87f 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -100,8 +100,8 @@ static int platram_remove(struct platform_device *pdev) /* release resources */ if (info->area) { - release_resource(info->area); - kfree(info->area); + release_mem_region(info->area->start, + resource_size(info->area)); } if (info->map.virt != NULL) -- 2.7.4
[PATCH v1] mtd: plat-ram: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting. Signed-off-by: Anton Vasilyev --- v1: Fix commit based on Boris Brezillon review --- drivers/mtd/maps/plat-ram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..90bc87f 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -100,8 +100,8 @@ static int platram_remove(struct platform_device *pdev) /* release resources */ if (info->area) { - release_resource(info->area); - kfree(info->area); + release_mem_region(info->area->start, + resource_size(info->area)); } if (info->map.virt != NULL) -- 2.7.4
[PATCH v4] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() performs pri_dai->sec_dai dereference in any case. The patch removes useless reinitialization of sec_dai at samsung_i2s_remove(), because resources are under devm control. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v2: Drop initialization of sec_dai by NULL at samsung_i2s_remove as Sylwester Nawrocki suggest. --- v3: Fix typo in the comment --- v4: Change comment based on Krzysztof review. --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH v4] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() performs pri_dai->sec_dai dereference in any case. The patch removes useless reinitialization of sec_dai at samsung_i2s_remove(), because resources are under devm control. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Drop initialization of sec_dai by NULL at samsung_i2s_remove as Sylwester Nawrocki suggest. --- v3: Fix typo in the comment --- v4: Change comment based on Krzysztof review. --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH v3] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() performs pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v2: Drop initialization of sec_dai by NULL at samsung_i2s_remove as Sylwester Nawrocki suggest. --- v3: Fix typo in the comment --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH v3] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() performs pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Drop initialization of sec_dai by NULL at samsung_i2s_remove as Sylwester Nawrocki suggest. --- v3: Fix typo in the comment --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH] video: fbdev: udlfb: Fix use after free on dlfb_usb_probe error path
If dlfb_usb_probe drops to error path then there is only one kref_init() call and no kref_get(), so second kref_put() leads to use after free. The patch removes superfluous kref_put on dlfb_usb_probe error path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/video/fbdev/udlfb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index 05ef657..f71b49f 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -1655,7 +1655,6 @@ static int dlfb_usb_probe(struct usb_interface *interface, error: if (dev) { - kref_put(>kref, dlfb_free); /* ref for framebuffer */ kref_put(>kref, dlfb_free); /* last ref from kref_init */ /* dev has been deallocated. Do not dereference */ -- 2.7.4
[PATCH] video: fbdev: udlfb: Fix use after free on dlfb_usb_probe error path
If dlfb_usb_probe drops to error path then there is only one kref_init() call and no kref_get(), so second kref_put() leads to use after free. The patch removes superfluous kref_put on dlfb_usb_probe error path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/video/fbdev/udlfb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index 05ef657..f71b49f 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -1655,7 +1655,6 @@ static int dlfb_usb_probe(struct usb_interface *interface, error: if (dev) { - kref_put(>kref, dlfb_free); /* ref for framebuffer */ kref_put(>kref, dlfb_free); /* last ref from kref_init */ /* dev has been deallocated. Do not dereference */ -- 2.7.4
[PATCH] mISDN: Fix null pointer dereference at mISDN_FsmNew
If mISDN_FsmNew() fails to allocate memory for jumpmatrix then null pointer dereference will occur on any write to jumpmatrix. The patch adds check on successful allocation and corresponding error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/isdn/mISDN/fsm.c| 5 - drivers/isdn/mISDN/fsm.h| 2 +- drivers/isdn/mISDN/layer1.c | 3 +-- drivers/isdn/mISDN/layer2.c | 15 +-- drivers/isdn/mISDN/tei.c| 20 +--- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c index 78fc5d5..92e6570 100644 --- a/drivers/isdn/mISDN/fsm.c +++ b/drivers/isdn/mISDN/fsm.c @@ -26,7 +26,7 @@ #define FSM_TIMER_DEBUG 0 -void +int mISDN_FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) { @@ -34,6 +34,8 @@ mISDN_FsmNew(struct Fsm *fsm, fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + if (fsm->jumpmatrix == NULL) + return -ENOMEM; for (i = 0; i < fncount; i++) if ((fnlist[i].state >= fsm->state_count) || @@ -45,6 +47,7 @@ mISDN_FsmNew(struct Fsm *fsm, } else fsm->jumpmatrix[fsm->state_count * fnlist[i].event + fnlist[i].state] = (FSMFNPTR) fnlist[i].routine; + return 0; } EXPORT_SYMBOL(mISDN_FsmNew); diff --git a/drivers/isdn/mISDN/fsm.h b/drivers/isdn/mISDN/fsm.h index 928f5be..e1def84 100644 --- a/drivers/isdn/mISDN/fsm.h +++ b/drivers/isdn/mISDN/fsm.h @@ -55,7 +55,7 @@ struct FsmTimer { void *arg; }; -extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int); +extern int mISDN_FsmNew(struct Fsm *, struct FsmNode *, int); extern void mISDN_FsmFree(struct Fsm *); extern int mISDN_FsmEvent(struct FsmInst *, int , void *); extern void mISDN_FsmChangeState(struct FsmInst *, int); diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c index bebc57b..3192b0e 100644 --- a/drivers/isdn/mISDN/layer1.c +++ b/drivers/isdn/mISDN/layer1.c @@ -414,8 +414,7 @@ l1_init(u_int *deb) l1fsm_s.event_count = L1_EVENT_COUNT; l1fsm_s.strEvent = strL1Event; l1fsm_s.strState = strL1SState; - mISDN_FsmNew(_s, L1SFnList, ARRAY_SIZE(L1SFnList)); - return 0; + return mISDN_FsmNew(_s, L1SFnList, ARRAY_SIZE(L1SFnList)); } void diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 7243a67..9ff0903 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -2247,15 +2247,26 @@ static struct Bprotocol X75SLP = { int Isdnl2_Init(u_int *deb) { + int res; debug = deb; mISDN_register_Bprotocol(); l2fsm.state_count = L2_STATE_COUNT; l2fsm.event_count = L2_EVENT_COUNT; l2fsm.strEvent = strL2Event; l2fsm.strState = strL2State; - mISDN_FsmNew(, L2FnList, ARRAY_SIZE(L2FnList)); - TEIInit(deb); + res = mISDN_FsmNew(, L2FnList, ARRAY_SIZE(L2FnList)); + if (res) + goto error; + res = TEIInit(deb); + if (res) + goto error_fsm; return 0; + +error_fsm: + mISDN_FsmFree(); +error: + mISDN_unregister_Bprotocol(); + return res; } void diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 908127e..12d9e5f 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1387,23 +1387,37 @@ create_teimanager(struct mISDNdevice *dev) int TEIInit(u_int *deb) { + int res; debug = deb; teifsmu.state_count = TEI_STATE_COUNT; teifsmu.event_count = TEI_EVENT_COUNT; teifsmu.strEvent = strTeiEvent; teifsmu.strState = strTeiState; - mISDN_FsmNew(, TeiFnListUser, ARRAY_SIZE(TeiFnListUser)); + res = mISDN_FsmNew(, TeiFnListUser, ARRAY_SIZE(TeiFnListUser)); + if (res) + goto error; teifsmn.state_count = TEI_STATE_COUNT; teifsmn.event_count = TEI_EVENT_COUNT; teifsmn.strEvent = strTeiEvent; teifsmn.strState = strTeiState; - mISDN_FsmNew(, TeiFnListNet, ARRAY_SIZE(TeiFnListNet)); + res = mISDN_FsmNew(, TeiFnListNet, ARRAY_SIZE(TeiFnListNet)); + if (res) + goto error_smn; deactfsm.state_count = DEACT_STATE_COUNT; deactfsm.event_count = DEACT_EVENT_COUNT; deactfsm.strEvent = strDeactEvent; deactfsm.strState = strDeactState; - mISDN_FsmNew(, DeactFnList, ARRAY_SIZE(DeactFnList)); + res = mISDN_FsmNew(, DeactFnList, ARRAY_SIZE(DeactFnList)); + if (res) + goto error_deact; return 0; + +error_deact: + mISDN_FsmFree(); +error_smn: + mISDN_FsmFree(); +error: + return res; } void TEIFree(void) -- 2.7.4
[PATCH] mISDN: Fix null pointer dereference at mISDN_FsmNew
If mISDN_FsmNew() fails to allocate memory for jumpmatrix then null pointer dereference will occur on any write to jumpmatrix. The patch adds check on successful allocation and corresponding error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/isdn/mISDN/fsm.c| 5 - drivers/isdn/mISDN/fsm.h| 2 +- drivers/isdn/mISDN/layer1.c | 3 +-- drivers/isdn/mISDN/layer2.c | 15 +-- drivers/isdn/mISDN/tei.c| 20 +--- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c index 78fc5d5..92e6570 100644 --- a/drivers/isdn/mISDN/fsm.c +++ b/drivers/isdn/mISDN/fsm.c @@ -26,7 +26,7 @@ #define FSM_TIMER_DEBUG 0 -void +int mISDN_FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) { @@ -34,6 +34,8 @@ mISDN_FsmNew(struct Fsm *fsm, fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + if (fsm->jumpmatrix == NULL) + return -ENOMEM; for (i = 0; i < fncount; i++) if ((fnlist[i].state >= fsm->state_count) || @@ -45,6 +47,7 @@ mISDN_FsmNew(struct Fsm *fsm, } else fsm->jumpmatrix[fsm->state_count * fnlist[i].event + fnlist[i].state] = (FSMFNPTR) fnlist[i].routine; + return 0; } EXPORT_SYMBOL(mISDN_FsmNew); diff --git a/drivers/isdn/mISDN/fsm.h b/drivers/isdn/mISDN/fsm.h index 928f5be..e1def84 100644 --- a/drivers/isdn/mISDN/fsm.h +++ b/drivers/isdn/mISDN/fsm.h @@ -55,7 +55,7 @@ struct FsmTimer { void *arg; }; -extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int); +extern int mISDN_FsmNew(struct Fsm *, struct FsmNode *, int); extern void mISDN_FsmFree(struct Fsm *); extern int mISDN_FsmEvent(struct FsmInst *, int , void *); extern void mISDN_FsmChangeState(struct FsmInst *, int); diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c index bebc57b..3192b0e 100644 --- a/drivers/isdn/mISDN/layer1.c +++ b/drivers/isdn/mISDN/layer1.c @@ -414,8 +414,7 @@ l1_init(u_int *deb) l1fsm_s.event_count = L1_EVENT_COUNT; l1fsm_s.strEvent = strL1Event; l1fsm_s.strState = strL1SState; - mISDN_FsmNew(_s, L1SFnList, ARRAY_SIZE(L1SFnList)); - return 0; + return mISDN_FsmNew(_s, L1SFnList, ARRAY_SIZE(L1SFnList)); } void diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 7243a67..9ff0903 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -2247,15 +2247,26 @@ static struct Bprotocol X75SLP = { int Isdnl2_Init(u_int *deb) { + int res; debug = deb; mISDN_register_Bprotocol(); l2fsm.state_count = L2_STATE_COUNT; l2fsm.event_count = L2_EVENT_COUNT; l2fsm.strEvent = strL2Event; l2fsm.strState = strL2State; - mISDN_FsmNew(, L2FnList, ARRAY_SIZE(L2FnList)); - TEIInit(deb); + res = mISDN_FsmNew(, L2FnList, ARRAY_SIZE(L2FnList)); + if (res) + goto error; + res = TEIInit(deb); + if (res) + goto error_fsm; return 0; + +error_fsm: + mISDN_FsmFree(); +error: + mISDN_unregister_Bprotocol(); + return res; } void diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 908127e..12d9e5f 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1387,23 +1387,37 @@ create_teimanager(struct mISDNdevice *dev) int TEIInit(u_int *deb) { + int res; debug = deb; teifsmu.state_count = TEI_STATE_COUNT; teifsmu.event_count = TEI_EVENT_COUNT; teifsmu.strEvent = strTeiEvent; teifsmu.strState = strTeiState; - mISDN_FsmNew(, TeiFnListUser, ARRAY_SIZE(TeiFnListUser)); + res = mISDN_FsmNew(, TeiFnListUser, ARRAY_SIZE(TeiFnListUser)); + if (res) + goto error; teifsmn.state_count = TEI_STATE_COUNT; teifsmn.event_count = TEI_EVENT_COUNT; teifsmn.strEvent = strTeiEvent; teifsmn.strState = strTeiState; - mISDN_FsmNew(, TeiFnListNet, ARRAY_SIZE(TeiFnListNet)); + res = mISDN_FsmNew(, TeiFnListNet, ARRAY_SIZE(TeiFnListNet)); + if (res) + goto error_smn; deactfsm.state_count = DEACT_STATE_COUNT; deactfsm.event_count = DEACT_EVENT_COUNT; deactfsm.strEvent = strDeactEvent; deactfsm.strState = strDeactState; - mISDN_FsmNew(, DeactFnList, ARRAY_SIZE(DeactFnList)); + res = mISDN_FsmNew(, DeactFnList, ARRAY_SIZE(DeactFnList)); + if (res) + goto error_deact; return 0; + +error_deact: + mISDN_FsmFree(); +error_smn: + mISDN_FsmFree(); +error: + return res; } void TEIFree(void) -- 2.7.4
[PATCH] mtd: plat-ram: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting. Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/mtd/maps/plat-ram.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..baaf146 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -82,6 +82,7 @@ static inline void platram_setrw(struct platram_info *info, int to) static int platram_remove(struct platform_device *pdev) { struct platram_info *info = to_platram_info(pdev); + resource_size_t res_size; dev_dbg(>dev, "removing device\n"); @@ -100,8 +101,8 @@ static int platram_remove(struct platform_device *pdev) /* release resources */ if (info->area) { - release_resource(info->area); - kfree(info->area); + res_size = resource_size(info->area) + release_mem_region(info->area->start, res_size); } if (info->map.virt != NULL) -- 2.7.4
[PATCH] mtd: plat-ram: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting. Signed-off-by: Anton Vasilyev --- drivers/mtd/maps/plat-ram.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 5157289..baaf146 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -82,6 +82,7 @@ static inline void platram_setrw(struct platram_info *info, int to) static int platram_remove(struct platform_device *pdev) { struct platram_info *info = to_platram_info(pdev); + resource_size_t res_size; dev_dbg(>dev, "removing device\n"); @@ -100,8 +101,8 @@ static int platram_remove(struct platform_device *pdev) /* release resources */ if (info->area) { - release_resource(info->area); - kfree(info->area); + res_size = resource_size(info->area) + release_mem_region(info->area->start, res_size); } if (info->map.virt != NULL) -- 2.7.4
[PATCH v2] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() permorms pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v2: Drop initialization of sec_dai at samsung_i2s_remove as Sylwester Nawrocki suggest. --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH v2] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() permorms pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Drop initialization of sec_dai at samsung_i2s_remove as Sylwester Nawrocki suggest. --- sound/soc/samsung/i2s.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6f896e3 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1376,13 +1376,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev) { - struct i2s_dai *pri_dai, *sec_dai; + struct i2s_dai *pri_dai; pri_dai = dev_get_drvdata(>dev); - sec_dai = pri_dai->sec_dai; - - pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH v2] hwmon:(stts751) buffer overread on wrong chip configuration
If stts751 hw by some reason reports conversion rate bigger then 9: ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); then dereference stts751_intervals[priv->interval] leads to buffer overread. The path adds sanity check for value stored on chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v2: Fixed Guenter's remark about comparison --- drivers/hwmon/stts751.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index d56251d..3f940fb 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -718,6 +718,10 @@ static int stts751_read_chip_config(struct stts751_priv *priv) ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); if (ret < 0) return ret; + if (ret >= ARRAY_SIZE(stts751_intervals)) { + dev_err(priv->dev, "Unrecognized conversion rate 0x%x\n", ret); + return -ENODEV; + } priv->interval = ret; ret = stts751_read_reg16(priv, >event_max, -- 2.7.4
[PATCH v2] hwmon:(stts751) buffer overread on wrong chip configuration
If stts751 hw by some reason reports conversion rate bigger then 9: ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); then dereference stts751_intervals[priv->interval] leads to buffer overread. The path adds sanity check for value stored on chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: Fixed Guenter's remark about comparison --- drivers/hwmon/stts751.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index d56251d..3f940fb 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -718,6 +718,10 @@ static int stts751_read_chip_config(struct stts751_priv *priv) ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); if (ret < 0) return ret; + if (ret >= ARRAY_SIZE(stts751_intervals)) { + dev_err(priv->dev, "Unrecognized conversion rate 0x%x\n", ret); + return -ENODEV; + } priv->interval = ret; ret = stts751_read_reg16(priv, >event_max, -- 2.7.4
[PATCH] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() permorms pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- sound/soc/samsung/i2s.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6beeea8 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1382,7 +1382,8 @@ static int samsung_i2s_remove(struct platform_device *pdev) sec_dai = pri_dai->sec_dai; pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; + if (sec_dai) + sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH] ASoC: samsung: i2s: Null pointer dereference on samsung_i2s_remove
If (quirks & QUIRK_SEC_DAI == 0) then samsung_i2s_probe() doesn't allocate sec_dai and pri_dai->sec_dai remains Null, but samsung_i2s_remove() permorms pri_dai->sec_dai dereference in any case. The patch adds sec_dai check on Null before derefence at samsung_i2s_remove(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- sound/soc/samsung/i2s.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index af3ba4d..6beeea8 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1382,7 +1382,8 @@ static int samsung_i2s_remove(struct platform_device *pdev) sec_dai = pri_dai->sec_dai; pri_dai->sec_dai = NULL; - sec_dai->pri_dai = NULL; + if (sec_dai) + sec_dai->pri_dai = NULL; pm_runtime_get_sync(>dev); pm_runtime_disable(>dev); -- 2.7.4
[PATCH] dmaengine: qcom_hidma: avoid freeing an uninitialized pointer
If device_node np doesn't contain child or first child doesn't have property "reg" then hidma_mgmt_of_populate_channels() perfoms deallocation on uninitialized local variable res. The patch adds res initialization by NULL. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/dma/qcom/hidma_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 5a0991b..89e36e3 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -354,7 +354,7 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) struct platform_device_info pdevinfo; struct of_phandle_args out_irq; struct device_node *child; - struct resource *res; + struct resource *res = NULL; const __be32 *cell; int ret = 0, size, i, num; u64 addr, addr_size; -- 2.7.4
[PATCH] dmaengine: qcom_hidma: avoid freeing an uninitialized pointer
If device_node np doesn't contain child or first child doesn't have property "reg" then hidma_mgmt_of_populate_channels() perfoms deallocation on uninitialized local variable res. The patch adds res initialization by NULL. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/dma/qcom/hidma_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c index 5a0991b..89e36e3 100644 --- a/drivers/dma/qcom/hidma_mgmt.c +++ b/drivers/dma/qcom/hidma_mgmt.c @@ -354,7 +354,7 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) struct platform_device_info pdevinfo; struct of_phandle_args out_irq; struct device_node *child; - struct resource *res; + struct resource *res = NULL; const __be32 *cell; int ret = 0, size, i, num; u64 addr, addr_size; -- 2.7.4
[PATCH] dvb-usb: Add memory free on error path in dw2102_probe()
If dw2102_probe() fails on dvb_usb_device_init(), then memleak occurs. The patch adds deallocation to the error path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/media/usb/dvb-usb/dw2102.c | 39 +- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6e654e5..0d63693 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2332,10 +2332,12 @@ 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; p1100 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!p1100) - return -ENOMEM; + goto err0; + /* copy default structure */ /* fill only different fields */ p1100->firmware = P1100_FIRMWARE; @@ -2346,10 +2348,9 @@ static int dw2102_probe(struct usb_interface *intf, s660 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s660) { - kfree(p1100); - return -ENOMEM; - } + if (!s660) + goto err1; + s660->firmware = S660_FIRMWARE; s660->num_device_descs = 3; s660->devices[0] = d660; @@ -2359,11 +2360,9 @@ static int dw2102_probe(struct usb_interface *intf, p7500 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!p7500) { - kfree(p1100); - kfree(s660); - return -ENOMEM; - } + if (!p7500) + goto err2; + p7500->firmware = P7500_FIRMWARE; p7500->devices[0] = d7500; p7500->rc.core.rc_query = prof_rc_query; @@ -2373,12 +2372,9 @@ static int dw2102_probe(struct usb_interface *intf, s421 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s421) { - kfree(p1100); - kfree(s660); - kfree(p7500); - return -ENOMEM; - } + if (!s421) + goto err3; + s421->num_device_descs = 2; s421->devices[0] = d421; s421->devices[1] = d632; @@ -2408,7 +2404,16 @@ static int dw2102_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr)) return 0; - return -ENODEV; + retval = -ENODEV; + kfree(s421); +err3: + kfree(p7500); +err2: + kfree(s660); +err1: + kfree(p1100); +err0: + return retval; } static void dw2102_disconnect(struct usb_interface *intf) -- 2.7.4
[PATCH] dvb-usb: Add memory free on error path in dw2102_probe()
If dw2102_probe() fails on dvb_usb_device_init(), then memleak occurs. The patch adds deallocation to the error path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/media/usb/dvb-usb/dw2102.c | 39 +- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6e654e5..0d63693 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2332,10 +2332,12 @@ 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; p1100 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!p1100) - return -ENOMEM; + goto err0; + /* copy default structure */ /* fill only different fields */ p1100->firmware = P1100_FIRMWARE; @@ -2346,10 +2348,9 @@ static int dw2102_probe(struct usb_interface *intf, s660 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s660) { - kfree(p1100); - return -ENOMEM; - } + if (!s660) + goto err1; + s660->firmware = S660_FIRMWARE; s660->num_device_descs = 3; s660->devices[0] = d660; @@ -2359,11 +2360,9 @@ static int dw2102_probe(struct usb_interface *intf, p7500 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!p7500) { - kfree(p1100); - kfree(s660); - return -ENOMEM; - } + if (!p7500) + goto err2; + p7500->firmware = P7500_FIRMWARE; p7500->devices[0] = d7500; p7500->rc.core.rc_query = prof_rc_query; @@ -2373,12 +2372,9 @@ static int dw2102_probe(struct usb_interface *intf, s421 = kmemdup(_properties, sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s421) { - kfree(p1100); - kfree(s660); - kfree(p7500); - return -ENOMEM; - } + if (!s421) + goto err3; + s421->num_device_descs = 2; s421->devices[0] = d421; s421->devices[1] = d632; @@ -2408,7 +2404,16 @@ static int dw2102_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr)) return 0; - return -ENODEV; + retval = -ENODEV; + kfree(s421); +err3: + kfree(p7500); +err2: + kfree(s660); +err1: + kfree(p1100); +err0: + return retval; } static void dw2102_disconnect(struct usb_interface *intf) -- 2.7.4
[PATCH] hwmon:(stts751) buffer overread on wrong chip configuration
If stts751 hw by some reason reports conversion rate bigger then 9: ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); then dereference stts751_intervals[priv->interval] leads to buffer overread. The path adds sanity check for value read from chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/hwmon/stts751.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index d56251d..f6eddbd 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -718,6 +718,10 @@ static int stts751_read_chip_config(struct stts751_priv *priv) ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); if (ret < 0) return ret; + if (ret > ARRAY_SIZE(stts751_intervals)) { + dev_err(priv->dev, "Unrecognized conversion rate 0x%x\n", ret); + return -ENODEV; + } priv->interval = ret; ret = stts751_read_reg16(priv, >event_max, -- 2.7.4
[PATCH] hwmon:(stts751) buffer overread on wrong chip configuration
If stts751 hw by some reason reports conversion rate bigger then 9: ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); then dereference stts751_intervals[priv->interval] leads to buffer overread. The path adds sanity check for value read from chip. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/hwmon/stts751.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index d56251d..f6eddbd 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -718,6 +718,10 @@ static int stts751_read_chip_config(struct stts751_priv *priv) ret = i2c_smbus_read_byte_data(priv->client, STTS751_REG_RATE); if (ret < 0) return ret; + if (ret > ARRAY_SIZE(stts751_intervals)) { + dev_err(priv->dev, "Unrecognized conversion rate 0x%x\n", ret); + return -ENODEV; + } priv->interval = ret; ret = stts751_read_reg16(priv, >event_max, -- 2.7.4
[PATCH] i2c: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/i2c/busses/i2c-simtec.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index b4685bb..adca51a 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -127,8 +127,7 @@ static int simtec_i2c_probe(struct platform_device *dev) iounmap(pd->reg); err_res: - release_resource(pd->ioarea); - kfree(pd->ioarea); + release_mem_region(pd->ioarea->start, size); err: kfree(pd); @@ -142,8 +141,7 @@ static int simtec_i2c_remove(struct platform_device *dev) i2c_del_adapter(>adap); iounmap(pd->reg); - release_resource(pd->ioarea); - kfree(pd->ioarea); + release_mem_region(pd->ioarea->start, resource_size(pd->ioarea)); kfree(pd); return 0; -- 2.7.4
[PATCH] i2c: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/i2c/busses/i2c-simtec.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index b4685bb..adca51a 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -127,8 +127,7 @@ static int simtec_i2c_probe(struct platform_device *dev) iounmap(pd->reg); err_res: - release_resource(pd->ioarea); - kfree(pd->ioarea); + release_mem_region(pd->ioarea->start, size); err: kfree(pd); @@ -142,8 +141,7 @@ static int simtec_i2c_remove(struct platform_device *dev) i2c_del_adapter(>adap); iounmap(pd->reg); - release_resource(pd->ioarea); - kfree(pd->ioarea); + release_mem_region(pd->ioarea->start, resource_size(pd->ioarea)); kfree(pd); return 0; -- 2.7.4
[PATCH] parport: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/parport/parport_ax88796.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c index 8f8c9f3..2fc91ed 100644 --- a/drivers/parport/parport_ax88796.c +++ b/drivers/parport/parport_ax88796.c @@ -358,8 +358,7 @@ static int parport_ax88796_probe(struct platform_device *pdev) exit_unmap: iounmap(dd->base); exit_res: - release_resource(dd->io); - kfree(dd->io); + release_mem_region(dd->io->start, size); exit_mem: kfree(dd); return ret; @@ -373,8 +372,7 @@ static int parport_ax88796_remove(struct platform_device *pdev) free_irq(p->irq, p); parport_remove_port(p); iounmap(dd->base); - release_resource(dd->io); - kfree(dd->io); + release_mem_region(dd->io->start, resource_size(dd->io)); kfree(dd); return 0; -- 2.7.4
[PATCH] parport: use release_mem_region instead of release_resource
Use api pair of request_mem_region and release_mem_region instead of release_resource. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/parport/parport_ax88796.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c index 8f8c9f3..2fc91ed 100644 --- a/drivers/parport/parport_ax88796.c +++ b/drivers/parport/parport_ax88796.c @@ -358,8 +358,7 @@ static int parport_ax88796_probe(struct platform_device *pdev) exit_unmap: iounmap(dd->base); exit_res: - release_resource(dd->io); - kfree(dd->io); + release_mem_region(dd->io->start, size); exit_mem: kfree(dd); return ret; @@ -373,8 +372,7 @@ static int parport_ax88796_remove(struct platform_device *pdev) free_irq(p->irq, p); parport_remove_port(p); iounmap(dd->base); - release_resource(dd->io); - kfree(dd->io); + release_mem_region(dd->io->start, resource_size(dd->io)); kfree(dd); return 0; -- 2.7.4
[PATCH] hw: Fix permissions for OCRDMA_RESET_STATS
Debugfs file reset_stats is created with S_IRUSR permissions, but ocrdma_dbgfs_ops_read() doesn't support OCRDMA_RESET_STATS, whereas ocrdma_dbgfs_ops_write() supports only OCRDMA_RESET_STATS. The patch fixes misstype with permissions. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/infiniband/hw/ocrdma/ocrdma_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index 66056f9..d42c617 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -834,7 +834,7 @@ void ocrdma_add_port_stats(struct ocrdma_dev *dev) dev->reset_stats.type = OCRDMA_RESET_STATS; dev->reset_stats.dev = dev; - if (!debugfs_create_file("reset_stats", S_IRUSR, dev->dir, + if (!debugfs_create_file("reset_stats", S_IWUSR, dev->dir, >reset_stats, _dbg_ops)) goto err; -- 2.7.4
[PATCH] hw: Fix permissions for OCRDMA_RESET_STATS
Debugfs file reset_stats is created with S_IRUSR permissions, but ocrdma_dbgfs_ops_read() doesn't support OCRDMA_RESET_STATS, whereas ocrdma_dbgfs_ops_write() supports only OCRDMA_RESET_STATS. The patch fixes misstype with permissions. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/infiniband/hw/ocrdma/ocrdma_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index 66056f9..d42c617 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -834,7 +834,7 @@ void ocrdma_add_port_stats(struct ocrdma_dev *dev) dev->reset_stats.type = OCRDMA_RESET_STATS; dev->reset_stats.dev = dev; - if (!debugfs_create_file("reset_stats", S_IRUSR, dev->dir, + if (!debugfs_create_file("reset_stats", S_IWUSR, dev->dir, >reset_stats, _dbg_ops)) goto err; -- 2.7.4
net: thunderx: Buffer overwrite on bgx_probe
Hello. While searching for memory errors in Linux kernel I've come across drivers/net/ethernet/cavium/thunder/thunder_bgx.ko module. I've found buffer overwrite at bgx_probe(): Consider device PCI_SUBSYS_DEVID_83XX_BGX. max_bgx_per_node is set to 4 by set_max_bgx_per_node(). Then on branch: pci_read_config_word(pdev, PCI_DEVICE_ID, ); if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) { bgx->bgx_id = (pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24) & BGX_ID_MASK; bgx->bgx_id += nic_get_node_id(pdev) * max_bgx_per_node; bgx->bgx_id could achieve value 3 + 3 * 4 = 15, which lead to buffer overwrite on bgx_vnic[bgx->bgx_id] = bgx; Question: is it enough for fix to change bgx_vnic's size? Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
net: thunderx: Buffer overwrite on bgx_probe
Hello. While searching for memory errors in Linux kernel I've come across drivers/net/ethernet/cavium/thunder/thunder_bgx.ko module. I've found buffer overwrite at bgx_probe(): Consider device PCI_SUBSYS_DEVID_83XX_BGX. max_bgx_per_node is set to 4 by set_max_bgx_per_node(). Then on branch: pci_read_config_word(pdev, PCI_DEVICE_ID, ); if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) { bgx->bgx_id = (pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24) & BGX_ID_MASK; bgx->bgx_id += nic_get_node_id(pdev) * max_bgx_per_node; bgx->bgx_id could achieve value 3 + 3 * 4 = 15, which lead to buffer overwrite on bgx_vnic[bgx->bgx_id] = bgx; Question: is it enough for fix to change bgx_vnic's size? Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
Buffer overread in pv88090-regulator.ko
Hello. While searching for memory errors in Linux kernel I've come across drivers/regulator/pv88090-regulator.ko module. Buffer overread could occur at pv88090_i2c_probe(): If read from malicious device such values for conf2 and range (e.g. 0x1000 and 0x1000 for PV88090_ID_BUCK2) that conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) & PV88090_BUCK_VDAC_RANGE_MASK; and range = (range >> (PV88080_BUCK_VRANGE_GAIN_SHIFT + i - 1)) & PV88080_BUCK_VRANGE_GAIN_MASK; become 1 then index = ((range << 1) | conf2); become 3, but index is used for dereference pv88090_buck_vol[3]. Should be index=3 considered as incorrect value and pv88090_i2c_probe() must return error, or pv88090_buck_vol[] should be expanded? Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
Buffer overread in pv88090-regulator.ko
Hello. While searching for memory errors in Linux kernel I've come across drivers/regulator/pv88090-regulator.ko module. Buffer overread could occur at pv88090_i2c_probe(): If read from malicious device such values for conf2 and range (e.g. 0x1000 and 0x1000 for PV88090_ID_BUCK2) that conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) & PV88090_BUCK_VDAC_RANGE_MASK; and range = (range >> (PV88080_BUCK_VRANGE_GAIN_SHIFT + i - 1)) & PV88080_BUCK_VRANGE_GAIN_MASK; become 1 then index = ((range << 1) | conf2); become 3, but index is used for dereference pv88090_buck_vol[3]. Should be index=3 considered as incorrect value and pv88090_i2c_probe() must return error, or pv88090_buck_vol[] should be expanded? Found by Linux Driver Verification project (linuxtesting.org). -- Anton Vasilyev Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: vasil...@ispras.ru
[PATCH v2] misc: Return error on error path
If ibmasm_event_buffer_init() or ibmasm_heartbeat_init() fails, then ibmasm_init_one() release all resources and return 0 on error path. The patch adds corresponding error for fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- v2: change ibmasm_event_buffer_init() to return corresponding error and check return values as Andy Shevchenko suggested. --- drivers/misc/ibmasm/event.c | 2 +- drivers/misc/ibmasm/module.c | 6 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c index 8e540f4..7e33025 100644 --- a/drivers/misc/ibmasm/event.c +++ b/drivers/misc/ibmasm/event.c @@ -155,7 +155,7 @@ int ibmasm_event_buffer_init(struct service_processor *sp) buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL); if (!buffer) - return 1; + return -ENOMEM; buffer->next_index = 0; buffer->next_serial_number = 1; diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index c5a456b..e914b8c 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -94,12 +94,14 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number); snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number); - if (ibmasm_event_buffer_init(sp)) { + result = ibmasm_event_buffer_init(sp); + if (result) { dev_err(sp->dev, "Failed to allocate event buffer\n"); goto error_eventbuffer; } - if (ibmasm_heartbeat_init(sp)) { + result = ibmasm_heartbeat_init(sp); + if (result) { dev_err(sp->dev, "Failed to allocate heartbeat command\n"); goto error_heartbeat; } -- 2.7.4
[PATCH v2] misc: Return error on error path
If ibmasm_event_buffer_init() or ibmasm_heartbeat_init() fails, then ibmasm_init_one() release all resources and return 0 on error path. The patch adds corresponding error for fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- v2: change ibmasm_event_buffer_init() to return corresponding error and check return values as Andy Shevchenko suggested. --- drivers/misc/ibmasm/event.c | 2 +- drivers/misc/ibmasm/module.c | 6 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c index 8e540f4..7e33025 100644 --- a/drivers/misc/ibmasm/event.c +++ b/drivers/misc/ibmasm/event.c @@ -155,7 +155,7 @@ int ibmasm_event_buffer_init(struct service_processor *sp) buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL); if (!buffer) - return 1; + return -ENOMEM; buffer->next_index = 0; buffer->next_serial_number = 1; diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index c5a456b..e914b8c 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -94,12 +94,14 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number); snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number); - if (ibmasm_event_buffer_init(sp)) { + result = ibmasm_event_buffer_init(sp); + if (result) { dev_err(sp->dev, "Failed to allocate event buffer\n"); goto error_eventbuffer; } - if (ibmasm_heartbeat_init(sp)) { + result = ibmasm_heartbeat_init(sp); + if (result) { dev_err(sp->dev, "Failed to allocate heartbeat command\n"); goto error_heartbeat; } -- 2.7.4
[PATCH] misc: Return error on error path
If ibmasm_event_buffer_init() or ibmasm_heartbeat_init() fails, then ibmasm_init_one() release all resources and return 0 on error path. The patch adds corresponding error for fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- drivers/misc/ibmasm/module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index c5a456b..ba76405 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -96,11 +96,13 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ibmasm_event_buffer_init(sp)) { dev_err(sp->dev, "Failed to allocate event buffer\n"); + result = -ENOMEM; goto error_eventbuffer; } if (ibmasm_heartbeat_init(sp)) { dev_err(sp->dev, "Failed to allocate heartbeat command\n"); + result = -ENOMEM; goto error_heartbeat; } -- 2.7.4
[PATCH] misc: Return error on error path
If ibmasm_event_buffer_init() or ibmasm_heartbeat_init() fails, then ibmasm_init_one() release all resources and return 0 on error path. The patch adds corresponding error for fails. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev --- drivers/misc/ibmasm/module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index c5a456b..ba76405 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -96,11 +96,13 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ibmasm_event_buffer_init(sp)) { dev_err(sp->dev, "Failed to allocate event buffer\n"); + result = -ENOMEM; goto error_eventbuffer; } if (ibmasm_heartbeat_init(sp)) { dev_err(sp->dev, "Failed to allocate heartbeat command\n"); + result = -ENOMEM; goto error_heartbeat; } -- 2.7.4
[tip:x86/cleanups] x86/paravirt: Remove unnecessary return from void function
Commit-ID: e8ad8bc403f49f8cb95448acfdeee39b459eded4 Gitweb: http://git.kernel.org/tip/e8ad8bc403f49f8cb95448acfdeee39b459eded4 Author: Anton Vasilyev <vasil...@ispras.ru> AuthorDate: Fri, 23 Jun 2017 19:23:13 +0300 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Sat, 24 Jun 2017 08:53:33 +0200 x86/paravirt: Remove unnecessary return from void function The patch removes unnecessary return from void function. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> Cc: Alok Kataria <akata...@vmware.com> Cc: Chris Wright <chr...@sous-sol.org> Cc: Jeremy Fitzhardinge <jer...@goop.org> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Rusty Russell <ru...@rustcorp.com.au> Cc: Thomas Gleixner <t...@linutronix.de> Cc: ldv-proj...@linuxtesting.org Cc: virtualizat...@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1498234993-1320-1-git-send-email-vasil...@ispras.ru Signed-off-by: Ingo Molnar <mi...@kernel.org> --- arch/x86/include/asm/paravirt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 55fa56f..a3dcf89 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -118,7 +118,7 @@ static inline u64 paravirt_read_msr(unsigned msr) static inline void paravirt_write_msr(unsigned msr, unsigned low, unsigned high) { - return PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); + PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); } static inline u64 paravirt_read_msr_safe(unsigned msr, int *err)
[tip:x86/cleanups] x86/paravirt: Remove unnecessary return from void function
Commit-ID: e8ad8bc403f49f8cb95448acfdeee39b459eded4 Gitweb: http://git.kernel.org/tip/e8ad8bc403f49f8cb95448acfdeee39b459eded4 Author: Anton Vasilyev AuthorDate: Fri, 23 Jun 2017 19:23:13 +0300 Committer: Ingo Molnar CommitDate: Sat, 24 Jun 2017 08:53:33 +0200 x86/paravirt: Remove unnecessary return from void function The patch removes unnecessary return from void function. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Cc: Alok Kataria Cc: Chris Wright Cc: Jeremy Fitzhardinge Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rusty Russell Cc: Thomas Gleixner Cc: ldv-proj...@linuxtesting.org Cc: virtualizat...@lists.linux-foundation.org Link: http://lkml.kernel.org/r/1498234993-1320-1-git-send-email-vasil...@ispras.ru Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 55fa56f..a3dcf89 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -118,7 +118,7 @@ static inline u64 paravirt_read_msr(unsigned msr) static inline void paravirt_write_msr(unsigned msr, unsigned low, unsigned high) { - return PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); + PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); } static inline u64 paravirt_read_msr_safe(unsigned msr, int *err)
[PATCH] x86: Remove unnecessary return from void function
The patch removes unnecessary return from void function. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev <vasil...@ispras.ru> --- arch/x86/include/asm/paravirt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 55fa56f..a3dcf89 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -118,7 +118,7 @@ static inline u64 paravirt_read_msr(unsigned msr) static inline void paravirt_write_msr(unsigned msr, unsigned low, unsigned high) { - return PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); + PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high); } static inline u64 paravirt_read_msr_safe(unsigned msr, int *err) -- 2.7.4