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 <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED]:/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 = 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 --- -- Eygene _ ___ _.--. # \`.|\..----...-'` `-._.-'_.-'` # Remember that it is hard / ' ` , __.--' # to read the on-line manual )/' _/ \ `-_, / # while single-stepping the kernel. `-'" `"\_ ,_.-;_.-\_ ', fsc/as # _.-'_./ {_.' ; / # -- FreeBSD Developers handbook {_.-``-' {_/ #
pgpwqDwJhhDzk.pgp
Description: PGP signature