[PATCH] media: dw2102: Fix use after free

2019-08-22 Thread Anton Vasilyev
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]

2018-08-07 Thread Anton Vasilyev
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]

2018-08-07 Thread Anton Vasilyev
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

2018-08-07 Thread Anton Vasilyev
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

2018-08-07 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-06 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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

2018-08-01 Thread Anton Vasilyev
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()

2018-07-27 Thread Anton Vasilyev
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()

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-27 Thread Anton Vasilyev
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

2018-07-24 Thread Anton Vasilyev
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

2018-07-24 Thread Anton Vasilyev
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

2018-07-24 Thread Anton Vasilyev
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

2018-07-24 Thread Anton Vasilyev
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

2018-07-23 Thread Anton Vasilyev

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

2018-07-23 Thread Anton Vasilyev

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

2018-07-23 Thread Anton Vasilyev
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

2018-07-23 Thread Anton Vasilyev
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

2018-07-23 Thread Anton Vasilyev
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

2018-07-23 Thread Anton Vasilyev
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

2018-07-06 Thread Anton Vasilyev
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

2018-07-06 Thread Anton Vasilyev
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

2018-06-19 Thread Anton Vasilyev
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

2018-06-19 Thread Anton Vasilyev
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

2018-06-13 Thread Anton Vasilyev
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

2018-06-13 Thread Anton Vasilyev
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]

2018-06-13 Thread Anton Vasilyev
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]

2018-06-13 Thread Anton Vasilyev
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

2018-06-13 Thread Anton Vasilyev
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

2018-06-13 Thread Anton Vasilyev
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

2018-06-09 Thread Anton Vasilyev
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

2018-06-09 Thread Anton Vasilyev
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

2017-08-22 Thread Anton Vasilyev


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

2017-08-22 Thread Anton Vasilyev


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

2017-08-22 Thread Anton Vasilyev
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

2017-08-22 Thread Anton Vasilyev
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

2017-08-16 Thread Anton Vasilyev
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

2017-08-16 Thread Anton Vasilyev
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

2017-08-16 Thread Anton Vasilyev



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

2017-08-16 Thread Anton Vasilyev



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

2017-08-16 Thread Anton Vasilyev
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

2017-08-16 Thread Anton Vasilyev
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

2017-08-15 Thread Anton Vasilyev
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

2017-08-15 Thread Anton Vasilyev
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

2017-08-15 Thread Anton Vasilyev
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

2017-08-15 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-11 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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()

2017-08-10 Thread Anton Vasilyev
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()

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-10 Thread Anton Vasilyev
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

2017-08-08 Thread Anton Vasilyev
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

2017-08-08 Thread Anton Vasilyev
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

2017-08-02 Thread Anton Vasilyev

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

2017-08-02 Thread Anton Vasilyev

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

2017-08-01 Thread Anton Vasilyev

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

2017-08-01 Thread Anton Vasilyev

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

2017-08-01 Thread Anton Vasilyev
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

2017-08-01 Thread Anton Vasilyev
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

2017-07-31 Thread Anton Vasilyev
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

2017-07-31 Thread Anton Vasilyev
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

2017-06-24 Thread tip-bot for Anton Vasilyev
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

2017-06-24 Thread tip-bot for Anton Vasilyev
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

2017-06-23 Thread Anton Vasilyev
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



  1   2   >