drivers: isdn: capi: Fix data-race bug
diff mbox series

Message ID 20200722172329.16727-1-madhuparnabhowmik10@gmail.com
State New
Headers show
Series
  • drivers: isdn: capi: Fix data-race bug
Related show

Commit Message

Madhuparna Bhowmik July 22, 2020, 5:23 p.m. UTC
From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>

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 <madhuparnabhowmik10@gmail.com>
---
 drivers/isdn/capi/capi.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

Comments

Arnd Bergmann July 22, 2020, 6:41 p.m. UTC | #1
On Wed, Jul 22, 2020 at 7:23 PM <madhuparnabhowmik10@gmail.com> wrote:
>
> From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
>
> 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 <madhuparnabhowmik10@gmail.com>

I don't think there are any users of this driver, but I had a look anyway.

The patch looks reasonable at first, but I'm not sure if you just
replace one race with another, since now the tty device can be
opened before the rest of the subsystem is initialized.

It's probably fine.

         Arnd
David Miller July 23, 2020, 10:11 p.m. UTC | #2
From: madhuparnabhowmik10@gmail.com
Date: Wed, 22 Jul 2020 22:53:29 +0530

> From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
> 
> 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 <madhuparnabhowmik10@gmail.com>

I agree with Arnd that this just exchanges one set of problems for
another.
Madhuparna Bhowmik July 24, 2020, 4:48 a.m. UTC | #3
On Thu, Jul 23, 2020 at 03:11:58PM -0700, David Miller wrote:
> From: madhuparnabhowmik10@gmail.com
> Date: Wed, 22 Jul 2020 22:53:29 +0530
> 
> > From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
> > 
> > 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 <madhuparnabhowmik10@gmail.com>
> 
> I agree with Arnd that this just exchanges one set of problems for
> another.

Thanks Arnd and David, for reviewing the patch.
Do you have any suggestions on how to fix this correctly?

Regards,
Madhuparna
Greg KH July 24, 2020, 6:57 a.m. UTC | #4
On Fri, Jul 24, 2020 at 10:18:07AM +0530, Madhuparna Bhowmik wrote:
> On Thu, Jul 23, 2020 at 03:11:58PM -0700, David Miller wrote:
> > From: madhuparnabhowmik10@gmail.com
> > Date: Wed, 22 Jul 2020 22:53:29 +0530
> > 
> > > From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
> > > 
> > > 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 <madhuparnabhowmik10@gmail.com>
> > 
> > I agree with Arnd that this just exchanges one set of problems for
> > another.
> 
> Thanks Arnd and David, for reviewing the patch.
> Do you have any suggestions on how to fix this correctly?

Based on the installed base of ISDN systems, and the fact that no one
has ever actually hit this race and reported it ever, I wouldn't worry
about it :)

thanks,

greg k-h
Madhuparna Bhowmik July 24, 2020, 2:58 p.m. UTC | #5
On Fri, Jul 24, 2020 at 08:57:47AM +0200, Greg KH wrote:
> On Fri, Jul 24, 2020 at 10:18:07AM +0530, Madhuparna Bhowmik wrote:
> > On Thu, Jul 23, 2020 at 03:11:58PM -0700, David Miller wrote:
> > > From: madhuparnabhowmik10@gmail.com
> > > Date: Wed, 22 Jul 2020 22:53:29 +0530
> > > 
> > > > From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
> > > > 
> > > > 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 <madhuparnabhowmik10@gmail.com>
> > > 
> > > I agree with Arnd that this just exchanges one set of problems for
> > > another.
> > 
> > Thanks Arnd and David, for reviewing the patch.
> > Do you have any suggestions on how to fix this correctly?
> 
> Based on the installed base of ISDN systems, and the fact that no one
> has ever actually hit this race and reported it ever, I wouldn't worry
> about it :)
>
Fair enough! Thanks for having a look.

Regards,
Madhuparna

> thanks,
> 
> greg k-h

Patch
diff mbox series

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", &capi_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