[PATCH] usb/c67x00/c67x00-drv: Fix Data Race bug

2020-08-26 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

Currently in c67x00_drv_probe() IRQ is requested before calling
c67x00_probe_sie() and hence if interrupt happens the reading of certain
variables in the handler can race with initialization of the variables,
for e.g. sie->sie_num is written in c67x00_probe_sie() and read in
 c67x00_hcd_irq().
Hence, this patch calls c67x00_probe_sie() before requesting IRQ in
probe.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/usb/c67x00/c67x00-drv.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 53838e7d4eef..2e816d5ca0eb 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -146,6 +146,9 @@ static int c67x00_drv_probe(struct platform_device *pdev)
c67x00_ll_init(c67x00);
c67x00_ll_hpi_reg_init(c67x00);
 
+   for (i = 0; i < C67X00_SIES; i++)
+   c67x00_probe_sie(>sie[i], c67x00, i);
+
ret = request_irq(res2->start, c67x00_irq, 0, pdev->name, c67x00);
if (ret) {
dev_err(>dev, "Cannot claim IRQ\n");
@@ -158,9 +161,6 @@ static int c67x00_drv_probe(struct platform_device *pdev)
goto reset_failed;
}
 
-   for (i = 0; i < C67X00_SIES; i++)
-   c67x00_probe_sie(>sie[i], c67x00, i);
-
platform_set_drvdata(pdev, c67x00);
 
return 0;
-- 
2.17.1



[PATCH v2] drivers: mmc: host: via-sdmmc: Fix data race bug

2020-08-22 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

via_save_pcictrlreg() should be called with host->lock held
as it writes to pm_pcictrl_reg, otherwise there can be a race
condition between via_sd_suspend() and via_sdc_card_detect().
The same pattern is used in the function via_reset_pcictrl()
as well, where via_save_pcictrlreg() is called with host->lock
held.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
v2: Rebase v5.9-rc1

 drivers/mmc/host/via-sdmmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 49dab9f42b6d..9b755ea0fa03 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1257,11 +1257,14 @@ static void __maybe_unused via_init_sdc_pm(struct 
via_crdr_mmc_host *host)
 static int __maybe_unused via_sd_suspend(struct device *dev)
 {
struct via_crdr_mmc_host *host;
+   unsigned long flags;
 
host = dev_get_drvdata(dev);
 
+   spin_lock_irqsave(>lock, flags);
via_save_pcictrlreg(host);
via_save_sdcreg(host);
+   spin_unlock_irqrestore(>lock, flags);
 
device_wakeup_enable(dev);
 
-- 
2.17.1



[PATCH v2] drivers/dma/dma-jz4780: Fix race condition between probe and irq handler

2020-08-20 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

In probe, IRQ is requested before zchan->id is initialized which can be
read in the irq handler. Hence, shift request irq after other initializations
complete.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 

---
Changes since v1:
Keep enable clock before request IRQ.
---
 drivers/dma/dma-jz4780.c | 38 +++---
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index 448f663da89c..8beed91428bd 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -879,24 +879,11 @@ static int jz4780_dma_probe(struct platform_device *pdev)
return -EINVAL;
}
 
-   ret = platform_get_irq(pdev, 0);
-   if (ret < 0)
-   return ret;
-
-   jzdma->irq = ret;
-
-   ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
- jzdma);
-   if (ret) {
-   dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
-   return ret;
-   }
-
jzdma->clk = devm_clk_get(dev, NULL);
if (IS_ERR(jzdma->clk)) {
dev_err(dev, "failed to get clock\n");
ret = PTR_ERR(jzdma->clk);
-   goto err_free_irq;
+   return ret;
}
 
clk_prepare_enable(jzdma->clk);
@@ -949,10 +936,23 @@ static int jz4780_dma_probe(struct platform_device *pdev)
jzchan->vchan.desc_free = jz4780_dma_desc_free;
}
 
+   ret = platform_get_irq(pdev, 0);
+   if (ret < 0)
+   goto err_disable_clk;
+
+   jzdma->irq = ret;
+
+   ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
+ jzdma);
+   if (ret) {
+   dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
+   goto err_disable_clk;
+   }
+
ret = dmaenginem_async_device_register(dd);
if (ret) {
dev_err(dev, "failed to register device\n");
-   goto err_disable_clk;
+   goto err_free_irq;
}
 
/* Register with OF DMA helpers. */
@@ -960,17 +960,17 @@ static int jz4780_dma_probe(struct platform_device *pdev)
 jzdma);
if (ret) {
dev_err(dev, "failed to register OF DMA controller\n");
-   goto err_disable_clk;
+   goto err_free_irq;
}
 
dev_info(dev, "JZ4780 DMA controller initialised\n");
return 0;
 
-err_disable_clk:
-   clk_disable_unprepare(jzdma->clk);
-
 err_free_irq:
free_irq(jzdma->irq, jzdma);
+
+err_disable_clk:
+   clk_disable_unprepare(jzdma->clk);
return ret;
 }
 
-- 
2.17.1



[PATCH] drivers/dma/dma-jz4780: Fix race condition between probe and irq handler

2020-08-16 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

In probe IRQ is requested before zchan->id is initialized which can be
read in the irq handler. Hence, shift request irq and enable clock after
other initializations complete. Here, enable clock part is not part of
the race, it is just shifted down after request_irq to keep the error
path same as before.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/dma/dma-jz4780.c | 44 
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index 448f663da89c..5cbc8c3bd6c7 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -879,28 +879,6 @@ static int jz4780_dma_probe(struct platform_device *pdev)
return -EINVAL;
}
 
-   ret = platform_get_irq(pdev, 0);
-   if (ret < 0)
-   return ret;
-
-   jzdma->irq = ret;
-
-   ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
- jzdma);
-   if (ret) {
-   dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
-   return ret;
-   }
-
-   jzdma->clk = devm_clk_get(dev, NULL);
-   if (IS_ERR(jzdma->clk)) {
-   dev_err(dev, "failed to get clock\n");
-   ret = PTR_ERR(jzdma->clk);
-   goto err_free_irq;
-   }
-
-   clk_prepare_enable(jzdma->clk);
-
/* Property is optional, if it doesn't exist the value will remain 0. */
of_property_read_u32_index(dev->of_node, "ingenic,reserved-channels",
   0, >chan_reserved);
@@ -949,6 +927,28 @@ static int jz4780_dma_probe(struct platform_device *pdev)
jzchan->vchan.desc_free = jz4780_dma_desc_free;
}
 
+   ret = platform_get_irq(pdev, 0);
+   if (ret < 0)
+   return ret;
+
+   jzdma->irq = ret;
+
+   ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
+ jzdma);
+   if (ret) {
+   dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
+   return ret;
+   }
+
+   jzdma->clk = devm_clk_get(dev, NULL);
+   if (IS_ERR(jzdma->clk)) {
+   dev_err(dev, "failed to get clock\n");
+   ret = PTR_ERR(jzdma->clk);
+   goto err_free_irq;
+   }
+
+   clk_prepare_enable(jzdma->clk);
+
ret = dmaenginem_async_device_register(dd);
if (ret) {
dev_err(dev, "failed to register device\n");
-- 
2.17.1



[PATCH] drivers: watchdog: pc87413_wdt: Fix Race condition bug

2020-08-13 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

After misc_register the open() callback can be called.
However the base address (swc_base_addr) is set after misc_register()
in init.
As a result, if open callback is called before pc87413_get_swc_base_addr()
then in the following call chain: pc87413_open() -> pc87413_refresh() ->
pc87413_swc_bank3() : The value of swc_base_addr will be -1.
Therefore, do misc_register() after pc87413_get_swc_base_addr().

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/watchdog/pc87413_wdt.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 73fbfc99083b..ad8b8af2bdc0 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -512,6 +512,10 @@ static int __init pc87413_init(void)
if (ret != 0)
pr_err("cannot register reboot notifier (err=%d)\n", ret);
 
+   pc87413_select_wdt_out();
+   pc87413_enable_swc();
+   pc87413_get_swc_base_addr();
+
ret = misc_register(_miscdev);
if (ret != 0) {
pr_err("cannot register miscdev on minor=%d (err=%d)\n",
@@ -520,10 +524,6 @@ static int __init pc87413_init(void)
}
pr_info("initialized. timeout=%d min\n", timeout);
 
-   pc87413_select_wdt_out();
-   pc87413_enable_swc();
-   pc87413_get_swc_base_addr();
-
if (!request_region(swc_base_addr, 0x20, MODNAME)) {
pr_err("cannot request SWC region at 0x%x\n", swc_base_addr);
ret = -EBUSY;
-- 
2.17.1



[PATCH] drivers: crypto: picoxcell_crypto: Fix potential race condition bug

2020-08-11 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

engine->stat_irq_thresh was initialized after device_create_file() in
the probe function, the initialization may race with call to
spacc_stat_irq_thresh_store() which updates engine->stat_irq_thresh,
therefore initialize it before creating the file in probe function.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/crypto/picoxcell_crypto.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/picoxcell_crypto.c 
b/drivers/crypto/picoxcell_crypto.c
index dac6eb37fff9..fb34bf92861d 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1685,11 +1685,6 @@ static int spacc_probe(struct platform_device *pdev)
goto err_clk_put;
}
 
-   ret = device_create_file(>dev, _attr_stat_irq_thresh);
-   if (ret)
-   goto err_clk_disable;
-
-
/*
 * Use an IRQ threshold of 50% as a default. This seems to be a
 * reasonable trade off of latency against throughput but can be
@@ -1697,6 +1692,10 @@ static int spacc_probe(struct platform_device *pdev)
 */
engine->stat_irq_thresh = (engine->fifo_sz / 2);
 
+   ret = device_create_file(>dev, _attr_stat_irq_thresh);
+   if (ret)
+   goto err_clk_disable;
+
/*
 * Configure the interrupts. We only use the STAT_CNT interrupt as we
 * only submit a new packet for processing when we complete another in
-- 
2.17.1



[PATCH] drivers: watchdog: rdc321x_wdt: Fix race condition bugs

2020-08-07 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

In rdc321x_wdt_probe(), rdc321x_wdt_device.queue is initialized
after misc_register(), hence if ioctl is called before its
initialization which can call rdc321x_wdt_start() function,
it will see an uninitialized value of rdc321x_wdt_device.queue,
hence initialize it before misc_register().
Also, rdc321x_wdt_device.default_ticks is accessed in reset()
function called from write callback, thus initialize it before
misc_register().

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/watchdog/rdc321x_wdt.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 57187efeb86f..f0c94ea51c3e 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -231,6 +231,8 @@ static int rdc321x_wdt_probe(struct platform_device *pdev)
 
rdc321x_wdt_device.sb_pdev = pdata->sb_pdev;
rdc321x_wdt_device.base_reg = r->start;
+   rdc321x_wdt_device.queue = 0;
+   rdc321x_wdt_device.default_ticks = ticks;
 
err = misc_register(_wdt_misc);
if (err < 0) {
@@ -245,14 +247,11 @@ static int rdc321x_wdt_probe(struct platform_device *pdev)
rdc321x_wdt_device.base_reg, RDC_WDT_RST);
 
init_completion(_wdt_device.stop);
-   rdc321x_wdt_device.queue = 0;
 
clear_bit(0, _wdt_device.inuse);
 
timer_setup(_wdt_device.timer, rdc321x_wdt_trigger, 0);
 
-   rdc321x_wdt_device.default_ticks = ticks;
-
dev_info(>dev, "watchdog init success\n");
 
return 0;
-- 
2.17.1



[PATCH] drivers: char: applicom.c: Add lock for protecting DeviceErrorCount

2020-08-03 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

The variable DeviceErrorCount is used to keep track of the number of
errors in read, write and interrupt routines, however it was not
protected by proper locking.
Therefore, this patch adds a spinlock: error_lock to protect the
variable.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/char/applicom.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 14b2d8034c51..6df7450b8b99 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -106,6 +106,7 @@ static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec);
 static unsigned int WriteErrorCount;   /* number of write error  */
 static unsigned int ReadErrorCount;/* number of read error   */
 static unsigned int DeviceErrorCount;  /* number of device error */
+DEFINE_SPINLOCK(error_lock);   /* lock to protect error count 
variables */
 
 static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *);
 static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *);
@@ -428,7 +429,9 @@ static ssize_t ac_write(struct file *file, const char 
__user *buf, size_t count,
spin_unlock_irqrestore([IndexCard].mutex, flags);
printk(KERN_WARNING "APPLICOM driver write error board %d, 
DataFromPcReady = %d\n",
   IndexCard,(int)readb(apbs[IndexCard].RamIO + 
DATA_FROM_PC_READY));
+   spin_lock_irqsave(_lock, flags);
DeviceErrorCount++;
+   spin_unlock_irqrestore(_lock, flags);
return -EIO;
}

@@ -593,7 +596,9 @@ static ssize_t ac_read (struct file *filp, char __user 
*buf, size_t count, loff_

printk(KERN_WARNING "APPLICOM driver read error 
board %d, DataToPcReady = %d\n",
   i,(int)readb(apbs[i].RamIO + 
DATA_TO_PC_READY));
+   spin_lock_irqsave(_lock, flags);
DeviceErrorCount++;
+   spin_unlock_irqrestore(_lock, flags);
return -EIO;
}

@@ -653,7 +658,9 @@ static irqreturn_t ac_interrupt(int vec, void *dev_instance)
if (readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2) {
printk(KERN_WARNING "APPLICOM driver interrupt 
err board %d, DataToPcReady = %d\n",
   i+1,(int)readb(apbs[i].RamIO + 
DATA_TO_PC_READY));
+   spin_lock(_lock);
DeviceErrorCount++;
+   spin_unlock(_lock);
}
 
if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && 
@@ -661,7 +668,9 @@ static irqreturn_t ac_interrupt(int vec, void *dev_instance)

printk(KERN_WARNING "APPLICOM driver interrupt 
err board %d, DataFromPcReady = %d\n",
   i+1,(int)readb(apbs[i].RamIO + 
DATA_FROM_PC_READY));
+   spin_lock(_lock);
DeviceErrorCount++;
+   spin_unlock(_lock);
}
 
if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { 
/* mailbox sent by the card ?   */
@@ -699,6 +708,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg)
  
 {  /* @ ADG ou ATO selon le cas */
int i;
+   unsigned long flags;
unsigned char IndexCard;
void __iomem *pmem;
int ret = 0;
@@ -819,12 +829,14 @@ static long ac_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg)
else
printk("\n");
}
+   spin_lock_irqsave(_lock, flags);
if (DeviceErrorCount != 0)
printk(KERN_INFO "DeviceErrorCount ... %d\n", 
DeviceErrorCount);
if (ReadErrorCount != 0)
printk(KERN_INFO "ReadErrorCount . %d\n", 
ReadErrorCount);
if (WriteErrorCount != 0)
printk(KERN_INFO "WriteErrorCount  %d\n", 
WriteErrorCount);
+   spin_unlock_irqrestore(_lock, flags);
if (waitqueue_active())
printk(KERN_INFO "Process in read pending\n");
for (i = 0; i < MAX_BOARD; i++) {
-- 
2.17.1



[PATCH] drivers: mmc: host: via-sdmmc: Fix data race bug

2020-08-03 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

via_save_pcictrlreg() should be called with host->lock held
as it writes to pm_pcictrl_reg, otherwise there can be a race
condition between via_sd_suspend() and via_sdc_card_detect().
The same pattern is used in the function via_reset_pcictrl()
as well, where via_save_pcictrlreg() is called with host->lock
held.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/mmc/host/via-sdmmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index ef95bce50889..e4d8126cd4e5 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1259,11 +1259,14 @@ static void via_init_sdc_pm(struct via_crdr_mmc_host 
*host)
 static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state)
 {
struct via_crdr_mmc_host *host;
+   unsigned long flags;
 
host = pci_get_drvdata(pcidev);
 
+   spin_lock_irqsave(>lock, flags);
via_save_pcictrlreg(host);
via_save_sdcreg(host);
+   spin_unlock_irqrestore(>lock, flags);
 
pci_save_state(pcidev);
pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
-- 
2.17.1



[PATCH] drivers: isdn: capi: Fix data-race bug

2020-07-22 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

In capi_init(), after register_chrdev() the file operation callbacks
can be called. However capinc_tty_init() is called later.
Since capiminors and capinc_tty_driver are initialized in
capinc_tty_init(), their initialization can race with their usage
in various callbacks like in capi_release().

Therefore, call capinc_tty_init() before register_chrdev to avoid
such race conditions.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Madhuparna Bhowmik 
---
 drivers/isdn/capi/capi.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 85767f52fe3c..7e8ab48a15af 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1332,7 +1332,7 @@ static int __init capinc_tty_init(void)
return 0;
 }
 
-static void __exit capinc_tty_exit(void)
+static void capinc_tty_exit(void)
 {
tty_unregister_driver(capinc_tty_driver);
put_tty_driver(capinc_tty_driver);
@@ -1420,29 +1420,28 @@ static int __init capi_init(void)
if (ret)
return ret;
 
+   if (capinc_tty_init() < 0) {
+   kcapi_exit();
+   return -ENOMEM;
+   }
+
major_ret = register_chrdev(capi_major, "capi20", _fops);
if (major_ret < 0) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
+   capinc_tty_exit();
kcapi_exit();
return major_ret;
}
capi_class = class_create(THIS_MODULE, "capi");
if (IS_ERR(capi_class)) {
unregister_chrdev(capi_major, "capi20");
+   capinc_tty_exit();
kcapi_exit();
return PTR_ERR(capi_class);
}
 
device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi20");
 
-   if (capinc_tty_init() < 0) {
-   device_destroy(capi_class, MKDEV(capi_major, 0));
-   class_destroy(capi_class);
-   unregister_chrdev(capi_major, "capi20");
-   kcapi_exit();
-   return -ENOMEM;
-   }
-
proc_init();
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-- 
2.17.1



[PATCH] rculist: Fix _list_check_srcu() macro

2020-07-13 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the macro _list_check_srcu() for CONFIG_PROVE_RCU_LIST =
False.

Reported-by: kernel test robot 
Signed-off-by: Madhuparna Bhowmik 
---
 include/linux/rculist.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 516b4feb2682..a435ad62b90b 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -73,7 +73,7 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
 #define __list_check_rcu(dummy, cond, extra...)
\
({ check_arg_count_one(extra); })
 
-#define __list_check_srcu(cond)
+#define __list_check_srcu(cond)TRUE
 #endif
 
 /*
-- 
2.17.1



[PATCH 1/2] rculist : Introduce list/hlist_for_each_entry_srcu() macros

2020-07-12 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

list/hlist_for_each_entry_rcu() provides an optional cond argument
to specify the lock held in the updater side.
However for SRCU read side, not providing the cond argument results
into false positive as whether srcu_read_lock is held or not is not
checked implicitly. Therefore, on read side the lockdep expression
srcu_read_lock_held(srcu struct) can solve this issue.

However, the function still fails to check the cases where srcu
protected list is traversed with rcu_read_lock() instead of
srcu_read_lock(). Therefore, to remove the false negative,
this patch introduces two new list traversal primitives :
list_for_each_entry_srcu() and hlist_for_each_entry_srcu().

Both of the functions have non-optional cond argument
as it is required for both read and update side, and simply checks
if the cond is true. For regular read side the lockdep expression
srcu_read_lock_head() can be passed as the cond argument to
list/hlist_for_each_entry_srcu().

Suggested-by: Paolo Bonzini 
Signed-off-by: Madhuparna Bhowmik 
---
 include/linux/rculist.h | 48 +
 1 file changed, 48 insertions(+)

diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index df587d181844..516b4feb2682 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -63,9 +63,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
RCU_LOCKDEP_WARN(!(cond) && !rcu_read_lock_any_held(),  \
 "RCU-list traversed in non-reader section!");  \
})
+
+#define __list_check_srcu(cond) \
+   ({   \
+   RCU_LOCKDEP_WARN(!(cond),\
+   "RCU-list traversed without holding the required lock!");\
+   })
 #else
 #define __list_check_rcu(dummy, cond, extra...)
\
({ check_arg_count_one(extra); })
+
+#define __list_check_srcu(cond)
 #endif
 
 /*
@@ -383,6 +391,25 @@ static inline void list_splice_tail_init_rcu(struct 
list_head *list,
>member != (head); \
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
+/**
+ * list_for_each_entry_srcu-   iterate over rcu list of given type
+ * @pos:   the type * to use as a loop cursor.
+ * @head:  the head for your list.
+ * @member:the name of the list_head within the struct.
+ * @cond:  lockdep expression for the lock required to traverse the list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by srcu_read_lock().
+ * The lockdep expression srcu_read_lock_held() can be passed as the
+ * cond argument from read side.
+ */
+#define list_for_each_entry_srcu(pos, head, member, cond)  \
+   for (__list_check_srcu(cond),   \
+pos = list_entry_rcu((head)->next, typeof(*pos), member);  \
+   >member != (head); \
+   pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
+
 /**
  * list_entry_lockless - get the struct for this entry
  * @ptr:the  list_head pointer.
@@ -681,6 +708,27 @@ static inline void hlist_add_behind_rcu(struct hlist_node 
*n,
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
 
+/**
+ * hlist_for_each_entry_srcu - iterate over rcu list of given type
+ * @pos:   the type * to use as a loop cursor.
+ * @head:  the head for your list.
+ * @member:the name of the hlist_node within the struct.
+ * @cond:  lockdep expression for the lock required to traverse the list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as hlist_add_head_rcu()
+ * as long as the traversal is guarded by srcu_read_lock().
+ * The lockdep expression srcu_read_lock_held() can be passed as the
+ * cond argument from read side.
+ */
+#define hlist_for_each_entry_srcu(pos, head, member, cond) \
+   for (__list_check_srcu(cond),   \
+pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\
+   typeof(*(pos)), member);\
+   pos;\
+   pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
+   &(pos)->member)), typeof(*(pos)), member))
+
 /**
  * hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for 
tracing)
  * @pos:   the type * to use as a loop cursor.
-- 
2.17.1



[PATCH 2/2] kvm: mmu: page_track: Fix RCU list API usage

2020-07-12 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

Use hlist_for_each_entry_srcu() instead of hlist_for_each_entry_rcu()
as it also checkes if the right lock is held.
Using hlist_for_each_entry_rcu() with a condition argument will not
report the cases where a SRCU protected list is traversed using
rcu_read_lock(). Hence, use hlist_for_each_entry_srcu().

Signed-off-by: Madhuparna Bhowmik 
---
 arch/x86/kvm/mmu/page_track.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index a7bcde34d1f2..a9cd17625950 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -229,7 +229,8 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, 
const u8 *new,
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_srcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_write)
n->track_write(vcpu, gpa, new, bytes, n);
srcu_read_unlock(>track_srcu, idx);
@@ -254,7 +255,8 @@ void kvm_page_track_flush_slot(struct kvm *kvm, struct 
kvm_memory_slot *slot)
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_srcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_flush_slot)
n->track_flush_slot(kvm, slot, n);
srcu_read_unlock(>track_srcu, idx);
-- 
2.17.1



[PATCH] rculist : Introduce list/hlist_for_each_entry_srcu() macros

2020-07-03 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

list/hlist_for_each_entry_rcu() provides an optional cond argument
to specify the lock held in the updater side.
However for SRCU read side, not providing the cond argument results
into false positive as whether srcu_read_lock is held or not is not
checked implicitly. Therefore, on read side the lockdep expression
srcu_read_lock_held(srcu struct) can solve this issue.

However, the function still fails to check the cases where srcu
protected list is traversed with rcu_read_lock() instead of
srcu_read_lock(). Therefore, to remove the false negative,
this patch introduces two new list traversal primitives :
list_for_each_entry_srcu() and hlist_for_each_entry_srcu().

Both of the functions have non-optional cond argument
as it is required for both read and update side, and simply checks
if the cond is true.

Suggested-by: Paolo Bonzini 
Signed-off-by: Madhuparna Bhowmik 
---
 include/linux/rculist.h | 44 +
 1 file changed, 44 insertions(+)

diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index df587d181844..04a7e5791c39 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -63,9 +63,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
RCU_LOCKDEP_WARN(!(cond) && !rcu_read_lock_any_held(),  \
 "RCU-list traversed in non-reader section!");  \
})
+
+#define __list_check_srcu(cond) \
+   ({   \
+   RCU_LOCKDEP_WARN(!(cond),\
+   "RCU-list traversed without holding the required lock!");\
+   })
 #else
 #define __list_check_rcu(dummy, cond, extra...)
\
({ check_arg_count_one(extra); })
+
+#define __list_check_srcu(cond)
 #endif
 
 /*
@@ -383,6 +391,23 @@ static inline void list_splice_tail_init_rcu(struct 
list_head *list,
>member != (head); \
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
+/**
+ * list_for_each_entry_srcu-   iterate over rcu list of given type
+ * @pos:   the type * to use as a loop cursor.
+ * @head:  the head for your list.
+ * @member:the name of the list_head within the struct.
+ * @cond:  lockdep expression for the lock required to traverse the list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by srcu_read_lock().
+ */
+#define list_for_each_entry_srcu(pos, head, member, cond)  \
+   for (__list_check_srcu(cond),   \
+pos = list_entry_rcu((head)->next, typeof(*pos), member);  \
+   >member != (head); \
+   pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
+
 /**
  * list_entry_lockless - get the struct for this entry
  * @ptr:the  list_head pointer.
@@ -681,6 +706,25 @@ static inline void hlist_add_behind_rcu(struct hlist_node 
*n,
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
 
+/**
+ * hlist_for_each_entry_srcu - iterate over rcu list of given type
+ * @pos:   the type * to use as a loop cursor.
+ * @head:  the head for your list.
+ * @member:the name of the hlist_node within the struct.
+ * @cond:  lockdep expression for the lock required to traverse the list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as hlist_add_head_rcu()
+ * as long as the traversal is guarded by srcu_read_lock().
+ */
+#define hlist_for_each_entry_srcu(pos, head, member, cond) \
+   for (__list_check_srcu(cond),   \
+pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\
+   typeof(*(pos)), member);\
+   pos;\
+   pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
+   &(pos)->member)), typeof(*(pos)), member))
+
 /**
  * hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for 
tracing)
  * @pos:   the type * to use as a loop cursor.
-- 
2.17.1



[PATCH v2] kvm: Fix false positive RCU usage warning

2020-05-16 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

Fix the following false positive warnings:

[ 9403.765413][T61744] =
[ 9403.786541][T61744] WARNING: suspicious RCU usage
[ 9403.807865][T61744] 5.7.0-rc1-next-20200417 #4 Tainted: G L
[ 9403.838945][T61744] -
[ 9403.860099][T61744] arch/x86/kvm/mmu/page_track.c:257 RCU-list traversed in 
non-reader section!!

and

[ 9405.859252][T61751] =
[ 9405.859258][T61751] WARNING: suspicious RCU usage
[ 9405.880867][T61755] -
[ 9405.911936][T61751] 5.7.0-rc1-next-20200417 #4 Tainted: G L
[ 9405.911942][T61751] -
[ 9405.911950][T61751] arch/x86/kvm/mmu/page_track.c:232 RCU-list traversed in 
non-reader section!!

Since srcu read lock is held, these are false positive warnings.
Therefore, pass condition srcu_read_lock_held() to
list_for_each_entry_rcu().

Reported-by: kernel test robot 
Signed-off-by: Madhuparna Bhowmik 
---
v2:
-Rebase v5.7-rc5

 arch/x86/kvm/mmu/page_track.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index ddc1ec3bdacd..1ad79c7aa05b 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -229,7 +229,8 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, 
const u8 *new,
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_rcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_write)
n->track_write(vcpu, gpa, new, bytes, n);
srcu_read_unlock(>track_srcu, idx);
@@ -254,7 +255,8 @@ void kvm_page_track_flush_slot(struct kvm *kvm, struct 
kvm_memory_slot *slot)
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_rcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_flush_slot)
n->track_flush_slot(kvm, slot, n);
srcu_read_unlock(>track_srcu, idx);
-- 
2.17.1



[PATCH net v2] ipv6: Fix suspicious RCU usage warning in ip6mr

2020-05-16 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning:

=
WARNING: suspicious RCU usage
5.7.0-rc4-next-20200507-syzkaller #0 Not tainted
-
net/ipv6/ip6mr.c:124 RCU-list traversed in non-reader section!!

ipmr_new_table() returns an existing table, but there is no table at
init. Therefore the condition: either holding rtnl or the list is empty
is used.

Fixes: d1db275dd3f6e ("ipv6: ip6mr: support multiple tables")
Reported-by: kernel test robot 
Suggested-by: Jakub Kicinski 
Signed-off-by: Madhuparna Bhowmik 
---
v2:
- Add correct fixes tag
- Fix line over 80 chars

 net/ipv6/ip6mr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 65a54d74acc1..1e223e26f079 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -98,7 +98,8 @@ static void ipmr_expire_process(struct timer_list *t);
 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
 #define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, >ipv6.mr6_tables, list, \
-   lockdep_rtnl_is_held())
+   lockdep_rtnl_is_held() || \
+   list_empty(>ipv6.mr6_tables))
 
 static struct mr_table *ip6mr_mr_table_iter(struct net *net,
struct mr_table *mrt)
-- 
2.17.1



[PATCH net] drivers: net: hamradio: Fix suspicious RCU usage warning in bpqether.c

2020-05-14 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning:
=
WARNING: suspicious RCU usage
5.7.0-rc5-next-20200514-syzkaller #0 Not tainted
-
drivers/net/hamradio/bpqether.c:149 RCU-list traversed in non-reader section!!

Since rtnl lock is held, pass this cond in list_for_each_entry_rcu().

Reported-by: syzbot+bb82cafc737c002d1...@syzkaller.appspotmail.com
Signed-off-by: Madhuparna Bhowmik 
---
 drivers/net/hamradio/bpqether.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index fbea6f232819..e2ad3c2e8df5 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -127,7 +127,8 @@ static inline struct net_device *bpq_get_ax25_dev(struct 
net_device *dev)
 {
struct bpqdev *bpq;
 
-   list_for_each_entry_rcu(bpq, _devices, bpq_list) {
+   list_for_each_entry_rcu(bpq, _devices, bpq_list,
+   lockdep_rtnl_is_held()) {
if (bpq->ethdev == dev)
return bpq->axdev;
}
-- 
2.17.1



[PATCH net] ipv6: Fix suspicious RCU usage warning in ip6mr

2020-05-14 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning:

=
WARNING: suspicious RCU usage
5.7.0-rc4-next-20200507-syzkaller #0 Not tainted
-
net/ipv6/ip6mr.c:124 RCU-list traversed in non-reader section!!

ipmr_new_table() returns an existing table, but there is no table at
init. Therefore the condition: either holding rtnl or the list is empty
is used.

Fixes: d13fee049f ("Default enable RCU list lockdep debugging with .."): 
WARNING: suspicious RCU usage
Reported-by: kernel test robot 
Suggested-by: Jakub Kicinski 
Signed-off-by: Madhuparna Bhowmik 
---
 net/ipv6/ip6mr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 65a54d74acc1..fbe282bb8036 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -98,7 +98,7 @@ static void ipmr_expire_process(struct timer_list *t);
 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
 #define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, >ipv6.mr6_tables, list, \
-   lockdep_rtnl_is_held())
+   lockdep_rtnl_is_held() ||  
list_empty(>ipv6.mr6_tables))
 
 static struct mr_table *ip6mr_mr_table_iter(struct net *net,
struct mr_table *mrt)
-- 
2.17.1



[PATCH] Fix suspicious RCU usage warning

2020-05-13 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning:

=
WARNING: suspicious RCU usage
5.7.0-rc4-next-20200507-syzkaller #0 Not tainted
-
net/ipv6/ip6mr.c:124 RCU-list traversed in non-reader section!!

ipmr_new_table() returns an existing table, but there is no table at
init. Therefore the condition: either holding rtnl or the list is empty
is used.

Suggested-by: Jakub Kicinski 
Signed-off-by: Madhuparna Bhowmik 

Signed-off-by: Madhuparna Bhowmik 
---
 net/ipv6/ip6mr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 65a54d74acc1..fbe282bb8036 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -98,7 +98,7 @@ static void ipmr_expire_process(struct timer_list *t);
 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
 #define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, >ipv6.mr6_tables, list, \
-   lockdep_rtnl_is_held())
+   lockdep_rtnl_is_held() ||  
list_empty(>ipv6.mr6_tables))
 
 static struct mr_table *ip6mr_mr_table_iter(struct net *net,
struct mr_table *mrt)
-- 
2.17.1



[PATCH] x86: Fix RCU list usage to avoid false positive warnings

2020-04-30 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

Use list_for_each_entry() instead of list_for_each_entry_rcu() whenever
spinlock or mutex is always held.
Otherwise, pass cond to list_for_each_entry_rcu().

Signed-off-by: Madhuparna Bhowmik 
---
 arch/x86/kernel/nmi.c  | 2 +-
 arch/x86/kvm/irq_comm.c| 3 ++-
 arch/x86/pci/mmconfig-shared.c | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 6407ea21fa1b..999dc6c134d2 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -195,7 +195,7 @@ void unregister_nmi_handler(unsigned int type, const char 
*name)
 
raw_spin_lock_irqsave(>lock, flags);
 
-   list_for_each_entry_rcu(n, >head, list) {
+   list_for_each_entry(n, >head, list) {
/*
 * the name passed in to describe the nmi handler
 * is used as the lookup key
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index c47d2acec529..5b88a648e079 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -258,7 +258,8 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned 
irqchip, unsigned pin,
idx = srcu_read_lock(>irq_srcu);
gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
if (gsi != -1)
-   hlist_for_each_entry_rcu(kimn, >arch.mask_notifier_list, 
link)
+   hlist_for_each_entry_rcu(kimn, >arch.mask_notifier_list, 
link,
+   srcu_read_lock_held(>irq_srcu))
if (kimn->irq == gsi)
kimn->func(kimn, mask);
srcu_read_unlock(>irq_srcu, idx);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 6fa42e9c4e6f..a096942690bd 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -797,7 +797,7 @@ int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
struct pci_mmcfg_region *cfg;
 
mutex_lock(_mmcfg_lock);
-   list_for_each_entry_rcu(cfg, _mmcfg_list, list)
+   list_for_each_entry(cfg, _mmcfg_list, list)
if (cfg->segment == seg && cfg->start_bus == start &&
cfg->end_bus == end) {
list_del_rcu(>list);
-- 
2.17.1



[PATCH] kvm: Fix false-positive RCU list related warnings

2020-04-30 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning and other usage of
RCU list in eventfd.c

[29179.937976][T75781] WARNING: suspicious RCU usage
[29179.942789][T75781] 5.7.0-rc3-next-20200429 #1 Tainted: G   O L
[29179.949752][T75781] -
[29179.954498][T75781] arch/x86/kvm/../../../virt/kvm/eventfd.c:472 RCU-list 
traversed in non-reader section!!

Pass srcu_read_lock_held() as cond to list_for_each_entry_rcu().

Reported-by: Qian Cai 
Signed-off-by: Madhuparna Bhowmik 
---
 virt/kvm/eventfd.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 67b6fc153e9c..a23787693127 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -77,7 +77,8 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)
 
idx = srcu_read_lock(>irq_srcu);
 
-   list_for_each_entry_rcu(irqfd, >list, resampler_link)
+   list_for_each_entry_rcu(irqfd, >list, resampler_link,
+srcu_read_lock_held(>irq_srcu))
eventfd_signal(irqfd->resamplefd, 1);
 
srcu_read_unlock(>irq_srcu, idx);
@@ -452,7 +453,7 @@ bool kvm_irq_has_notifier(struct kvm *kvm, unsigned 
irqchip, unsigned pin)
gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
if (gsi != -1)
hlist_for_each_entry_rcu(kian, >irq_ack_notifier_list,
-link)
+link, 
srcu_read_lock_held(>irq_srcu))
if (kian->gsi == gsi) {
srcu_read_unlock(>irq_srcu, idx);
return true;
@@ -469,7 +470,7 @@ void kvm_notify_acked_gsi(struct kvm *kvm, int gsi)
struct kvm_irq_ack_notifier *kian;
 
hlist_for_each_entry_rcu(kian, >irq_ack_notifier_list,
-link)
+link, srcu_read_lock_held(>irq_srcu))
if (kian->gsi == gsi)
kian->irq_acked(kian);
 }
@@ -960,3 +961,4 @@ kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 
return kvm_assign_ioeventfd(kvm, args);
 }
+
-- 
2.17.1



[PATCH] integrity: evm: Fix RCU list related warnings.

2020-04-30 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

This patch fixes the following warning and few other
instances of traversal of evm_config_xattrnames list:

[   32.848432] =
[   32.848707] WARNING: suspicious RCU usage
[   32.848966] 5.7.0-rc1-6-ga8d5875ce5f0b #1 Not tainted
[   32.849308] -
[   32.849567] security/integrity/evm/evm_main.c:231 RCU-list traversed in 
non-reader section!!

Since entries are only added to the list and never deleted,
use list_For_each_entry_lockless() instead of
list_for_each_entry_rcu() for traversing the list.
Also, add a relevant comment in evm_secfs.c to indicate this fact.

Reported-by: kernel test robot 
Suggested-by: Paul E. McKenney 
Signed-off-by: Madhuparna Bhowmik 
---
 security/integrity/evm/evm_crypto.c | 2 +-
 security/integrity/evm/evm_main.c   | 4 ++--
 security/integrity/evm/evm_secfs.c  | 9 -
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/security/integrity/evm/evm_crypto.c 
b/security/integrity/evm/evm_crypto.c
index 35682852ddea..b2dc87da5f50 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -207,7 +207,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
data->hdr.length = crypto_shash_digestsize(desc->tfm);
 
error = -ENODATA;
-   list_for_each_entry_rcu(xattr, _config_xattrnames, list) {
+   list_for_each_entry_lockless(xattr, _config_xattrnames, list) {
bool is_ima = false;
 
if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
diff --git a/security/integrity/evm/evm_main.c 
b/security/integrity/evm/evm_main.c
index d361d7fdafc4..0d36259b690d 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -97,7 +97,7 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
if (!(inode->i_opflags & IOP_XATTR))
return -EOPNOTSUPP;
 
-   list_for_each_entry_rcu(xattr, _config_xattrnames, list) {
+   list_for_each_entry_lockless(xattr, _config_xattrnames, list) {
error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
if (error < 0) {
if (error == -ENODATA)
@@ -228,7 +228,7 @@ static int evm_protected_xattr(const char *req_xattr_name)
struct xattr_list *xattr;
 
namelen = strlen(req_xattr_name);
-   list_for_each_entry_rcu(xattr, _config_xattrnames, list) {
+   list_for_each_entry_lockless(xattr, _config_xattrnames, list) {
if ((strlen(xattr->name) == namelen)
&& (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
found = 1;
diff --git a/security/integrity/evm/evm_secfs.c 
b/security/integrity/evm/evm_secfs.c
index 39ad1038d45d..cfc3075769bb 100644
--- a/security/integrity/evm/evm_secfs.c
+++ b/security/integrity/evm/evm_secfs.c
@@ -232,7 +232,14 @@ static ssize_t evm_write_xattrs(struct file *file, const 
char __user *buf,
goto out;
}
 
-   /* Guard against races in evm_read_xattrs */
+   /*
+* xattr_list_mutex guards against races in evm_read_xattrs().
+* Entries are only added to the evm_config_xattrnames list
+* and never deleted. Therefore, the list is traversed
+* using list_for_each_entry_lockless() without holding
+* the mutex in evm_calc_hmac_or_hash(), evm_find_protected_xattrs()
+* and evm_protected_xattr().
+*/
mutex_lock(_list_mutex);
list_for_each_entry(tmp, _config_xattrnames, list) {
if (strcmp(xattr->name, tmp->name) == 0) {
-- 
2.17.1



[PATCH] kvm: Fix false positive RCU usage warning

2020-04-28 Thread madhuparnabhowmik10
From: Madhuparna Bhowmik 

Fix the following false positive warnings:

[ 9403.765413][T61744] =
[ 9403.786541][T61744] WARNING: suspicious RCU usage
[ 9403.807865][T61744] 5.7.0-rc1-next-20200417 #4 Tainted: G L
[ 9403.838945][T61744] -
[ 9403.860099][T61744] arch/x86/kvm/mmu/page_track.c:257 RCU-list traversed in 
non-reader section!!

and

[ 9405.859252][T61751] =
[ 9405.859258][T61751] WARNING: suspicious RCU usage
[ 9405.880867][T61755] -
[ 9405.911936][T61751] 5.7.0-rc1-next-20200417 #4 Tainted: G L
[ 9405.911942][T61751] -
[ 9405.911950][T61751] arch/x86/kvm/mmu/page_track.c:232 RCU-list traversed in 
non-reader section!!

Since srcu read lock is held, these are false positive warnings.
Therefore, pass condition srcu_read_lock_held() to
list_for_each_entry_rcu().

Reported-by: kernel test robot 
Signed-off-by: Madhuparna Bhowmik 
---
 arch/x86/kvm/mmu/page_track.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index ddc1ec3bdacd..1ad79c7aa05b 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -229,7 +229,8 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, 
const u8 *new,
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_rcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_write)
n->track_write(vcpu, gpa, new, bytes, n);
srcu_read_unlock(>track_srcu, idx);
@@ -254,7 +255,8 @@ void kvm_page_track_flush_slot(struct kvm *kvm, struct 
kvm_memory_slot *slot)
return;
 
idx = srcu_read_lock(>track_srcu);
-   hlist_for_each_entry_rcu(n, >track_notifier_list, node)
+   hlist_for_each_entry_rcu(n, >track_notifier_list, node,
+   srcu_read_lock_held(>track_srcu))
if (n->track_flush_slot)
n->track_flush_slot(kvm, slot, n);
srcu_read_unlock(>track_srcu, idx);
-- 
2.17.1