Date: Wed, 17 Sep 2008 21:42:00 +0400 From: Eygene Ryabinkin <rea-fbsd@codelabs.ru> To: Maksim Yevmenkin <maksim.yevmenkin@gmail.com> Cc: rik@freebsd.org, hackers@freebsd.org Subject: Re: kern/127446: [patch] fix race in sys/dev/kbdmux/kbdmux.c Message-ID: <gaH7cu1zt0Bw5e8Q2XfgrlKSRyY@iXA9ZWPrtc2I2BMzBXoToMd7YdQ> In-Reply-To: <bb4a86c70809170956x36234893he8894a49127b6b6e@mail.gmail.com> References: <20080917161633.9E2F717101@shadow.codelabs.ru> <bb4a86c70809170956x36234893he8894a49127b6b6e@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--MGYHOYXEY6WxJCY8 Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Maxim, good day. Cc'ing this discuission to hackers@ -- I was just going to write the separate letter on this topic to the list. Wed, Sep 17, 2008 at 09:56:14AM -0700, Maksim Yevmenkin wrote: > have you tried to simply set KBDMUX_LOCK/UNLOCK() to > mtx_lock/unlock(&Giant) ? Since kbdmux callout is initialized as non-MPSAFE, this will result in double locking the Giant (at least I see it from the code). I am not sure that this is very good -- had not yet verified that Giant is recursive. Can try it tomorrow. Since you had written the code and #if 0'ed the locking part, may I ask, why? Are there any known issues or it was just not very good to introduce locking at that time (rev. 1.1, 3 years ago)? Thanks! > On Wed, Sep 17, 2008 at 9:16 AM, Eygene Ryabinkin <rea-fbsd@codelabs.ru> = wrote: > >>Number: 127446 > >>Category: kern > >>Synopsis: [patch] fix race in sys/dev/kbdmux/kbdmux.c > >>Confidential: no > >>Severity: critical > >>Priority: high > >>Responsible: freebsd-bugs > >>State: open > >>Quarter: > >>Keywords: > >>Date-Required: > >>Class: sw-bug > >>Submitter-Id: current-users > >>Arrival-Date: Wed Sep 17 16:20:02 UTC 2008 > >>Closed-Date: > >>Last-Modified: > >>Originator: Eygene Ryabinkin > >>Release: FreeBSD 7.1-PRERELEASE amd64 > >>Organization: > > Code Labs > >>Environment: > > > > System: FreeBSD XXX 7.1-PRERELEASE FreeBSD 7.1-PRERELEASE #55: Wed Sep = 17 19:57:25 MSD 2008 root@XXX:/usr/src/sys/amd64/compile/XXX amd64 > > > > CVSupped system yesterday late at the evening (aroung 17:00 UTC). > > > >>Description: > > > > Since kbdmux(4) is not MPSAFE now, its interrupt routines are running > > under Giant. But there is kbdmux_read_char() routine that runs unlocked > > and can race with the interrupt handler. When there is no input data > > in the keyboard queue and kbdmux(4) is in the POLLING mode, routine will > > try to poll each mux member for the scancode. And if user presses the > > key at that time, KBDMUX_READ_CHAR() can race with the interrupt handler > > kbdmux_kbd_event() since we don't lock polling loop. > > > >>How-To-Repeat: > > > > I see this on my laptop: sometimes during boot, when system asks me for > > the password of geli(8)-encrypted volume, it doubles the symbols or even > > panics. I don't see this on the other systems, so perhaps my laptop is > > just so lucky ;)) > > > > But one can try to enable echoing of the input symbols during the geli's > > bootup password dialog (setting g_eli_visible_passphrase to 1 > > unconditionally) and maybe symbols will be doubled. I see this issue > > only during boot-up phase, but I feel that this is due to the fact that > > for the rest of the system's operation only interrupt handler is > > working, at least I see it from the debug printf()s. > > > >>Fix: > > > > The following patch fixes the things for me. It just acquires Giant for > > the time of polling. I did a limited testing at my systems and there > > were no signs of regressions yet. > > > > Seems like in the properly locked situation (with non-dummy KBDMUX_LOCK > > and KBDMUX_UNLOCK) this issue will vanish, so I had conditionalized > > Giant grabbing. > > > > --- kbdmux-read-race.patch begins here --- > > --- sys/dev/kbdmux/kbdmux.c.orig 2008-09-17 10:41:00.000000000 += 0400 > > +++ sys/dev/kbdmux/kbdmux.c 2008-09-17 19:52:00.000000000 +0400 > > @@ -79,6 +79,10 @@ > > */ > > > > #if 0 /* not yet */ > > +#define KBDMUX_LOCK_POLLER(dummy) > > + > > +#define KBDMUX_UNLOCK_POLLER(dummy) > > + > > #define KBDMUX_LOCK_DECL_GLOBAL \ > > struct mtx ks_lock > > #define KBDMUX_LOCK_INIT(s) \ > > @@ -98,6 +102,10 @@ > > #define KBDMUX_QUEUE_INTR(s) \ > > taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task) > > #else > > +#define KBDMUX_LOCK_POLLER(dummy) \ > > + mtx_lock(&Giant) > > +#define KBDMUX_UNLOCK_POLLER(dummy) \ > > + mtx_unlock(&Giant) > > #define KBDMUX_LOCK_DECL_GLOBAL > > > > #define KBDMUX_LOCK_INIT(s) > > @@ -661,6 +669,14 @@ > > if (state->ks_flags & POLLING) { > > kbdmux_kbd_t *k; > > > > + /* > > + * Grab Giant: we don't want to race with > > + * the keyboard interrupt handler. And this > > + * can happen, because when a key will be > > + * pressed, our READ_CHAR will be competing > > + * with the kbdmux_kbd_event()'s one. > > + */ > > + KBDMUX_LOCK_POLLER(); > > SLIST_FOREACH(k, &state->ks_kbds, next) { > > while (KBDMUX_CHECK_CHAR(k->kbd)) { > > scancode =3D KBDMUX_READ_CHAR(k-= >kbd, 0); > > @@ -674,6 +690,7 @@ > > putc(scancode, &state->ks_inq); > > } > > } > > + KBDMUX_UNLOCK_POLLER(); > > > > if (state->ks_inq.c_cc > 0) > > goto next_code; > > --- kbdmux-read-race.patch ends here --- --=20 Eygene _ ___ _.--. # \`.|\..----...-'` `-._.-'_.-'` # Remember that it is hard / ' ` , __.--' # to read the on-line manual =20 )/' _/ \ `-_, / # while single-stepping the kernel. `-'" `"\_ ,_.-;_.-\_ ', fsc/as # _.-'_./ {_.' ; / # -- FreeBSD Developers handbook=20 {_.-``-' {_/ # --MGYHOYXEY6WxJCY8 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (FreeBSD) iEYEARECAAYFAkjRQWgACgkQthUKNsbL7Yjv4QCfeZCRAyyrp4ax4CU3mtP8oX24 lxgAn2WLb9S3ZFQUJK5qiaeUUYAa4yPG =zuGF -----END PGP SIGNATURE----- --MGYHOYXEY6WxJCY8--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?gaH7cu1zt0Bw5e8Q2XfgrlKSRyY>