NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/51785: Accessing speaker device does not prevent its removal



>Number:         51785
>Category:       kern
>Synopsis:       Accessing speaker device does not prevent its removal
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jan 06 03:25:00 +0000 2017
>Originator:     Paul Goyette
>Release:        NetBSD 7.99.53
>Organization:
+------------------+--------------------------+------------------------+
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:      |
| (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com   |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org |
+------------------+--------------------------+------------------------+
>Environment:
	
	
System: NetBSD speedy.whooppee.com 7.99.53 NetBSD 7.99.53 (SPEEDY 2016-12-31 23:00:24) #1: Sun Jan 1 01:39:34 UTC 2017 paul%speedy.whooppee.com@localhost:/build/netbsd-local/obj/amd64/sys/arch/amd64/compile/SPEEDY amd64
Architecture: x86_64
Machine: amd64
>Description:
I started to write a MODULE_CMD_FINI routine for the spkr module.  It
seems that if the spkr device is busy playing something, it is still
possible to call config_fini_component() for the driver with a success
return code.  As a result, the driver assumes that it is safe to be
unloaded.

After the current play-string finishes, I/O completion code returns to
memory that no longer contains the driver, resulting in a panic.
	
>How-To-Repeat:
1. Build a kernel that does NOT have the spkr driver built-in, and
   with the following patch (with appropriate substitution of tab
   characters for white-space):

diff -u -p -r1.5 spkr.c
--- spkr.c      15 Dec 2016 06:55:55 -0000      1.5
+++ spkr.c      6 Jan 2017 03:11:05 -0000
@@ -493,20 +493,21 @@ spkr_modcmd(modcmd_t cmd, void *arg)
                        break;
 
                error = config_init_component(cfdriver_ioconf_spkr,
-                       cfattach_ioconf_spkr, cfdata_ioconf_spkr);
+                   cfattach_ioconf_spkr, cfdata_ioconf_spkr);
                if (error) {
                        devsw_detach(NULL, &spkr_cdevsw);
                }
                break;
 
        case MODULE_CMD_FINI:
-               return EBUSY;
-#ifdef notyet
-               error = config_fini_component(cfdriver_ioconf_spkr,
-                       cfattach_ioconf_spkr, cfdata_ioconf_spkr);
                devsw_detach(NULL, &spkr_cdevsw);
+               error = config_fini_component(cfdriver_ioconf_spkr,
+                   cfattach_ioconf_spkr, cfdata_ioconf_spkr);
+               if (error)
+                       devsw_attach(spkr_cd.cd_name, NULL, &bmajor,
+                           &spkr_cdevsw, &cmajor);
                break;
-#endif
+
        default:
                error = ENOTTY;
                break;

2. play a string to the /dev/speaker in the background:

	echo T60L1CP1CP1C > /dev/speaker &

3. while it is still playing, modunload spkr
	
>Fix:
Some sort of interlock would normally be held while the device is open
(the "echo" command above does not complete until the playstring is
finished).  This interlock would result in a failure to detach the
driver's data structures;  ie, you would get a failure from one or more
of config_{cfdata,cfattach,cfdriver}_detach().  This would cause the
call to config_fini_component() to fail, preventing the module from
being unloaded.
	

>Unformatted:
 	
 	


Home | Main Index | Thread Index | Old Index