Date: Tue, 26 May 2015 18:03:52 +1000 (EST) From: Bruce Evans <brde@optusnet.com.au> To: John-Mark Gurney <jmg@funkthat.com> Cc: Ian Lepore <ian@freebsd.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r283547 - head/sys/arm/conf Message-ID: <20150526153023.F914@besplex.bde.org> In-Reply-To: <20150525235147.GJ37063@funkthat.com> References: <201505252327.t4PNRDaA033870@svn.freebsd.org> <20150525235147.GJ37063@funkthat.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 25 May 2015, John-Mark Gurney wrote: > Ian Lepore wrote this message on Mon, May 25, 2015 at 23:27 +0000: >> Author: ian >> Date: Mon May 25 23:27:13 2015 >> New Revision: 283547 >> URL: https://svnweb.freebsd.org/changeset/base/283547 >> >> Log: >> Ensure that all arm kernel configs contain ALT_BREAK_TO_DEBUGGER and not >> BREAK_TO_DEBUGGER if they have a serial console (most do). A burst of >> serial line noise (such as unplugging a usb serial adapter) can look like >> a break and drop a working system into the debugger. The alt break sequence >> (<CR>~^B) works fine on both serial and non-serial consoles. > > Just so you know, this removes support for video console to break into > the debugger via keyboard... This mean ctrl-alt-esc and other key > sequences won't work anymore... Actually, it only breaks the usual non-sequences ctrl-prtscrn and ctrl-alt-esc. All console drivers support ALT_BREAK_TO_DEBUGGER, so escape sequences still work if this option is configured, but these quences are harder to remember and harder to type (I often forget where \n goes in them, or mistype it) and were not needed before except for serial consoles, so at most users of serial consoles will know them. Most of this is broken. 1. The BREAK in BREAK_TO_DEBUGGER means a serial line break. This is now confused with "breaking" into the debugger in all sorts of ways, and/or with the breakpoint() function used to implement "breaking" into the debugger in some of these ways. The breakpoint() function has a generic name although not all arches have a breakpoint instruction in hardware, at least by name. kdb_break() is misnamed. It is just a wrapper for kdb_enter() that supplies the (wrong) entry code KDB_WHY_BREAK and the (wrong) message "Break to debugger". Here BREAK and "Break" have nothing to do with serial line breaks or the (virtual) breakpoint instruction. They mean "break" in the sense of "stop the normal execution and enter the debugger". Normal uses of the breakpoint instruction don't go via this path -- they have already executed the instruction, while this path will execute the instruction. 2. BREAK_TO_DEBUGGER with its non-broken meaning is unusable for most systems since it causes the problems mentioned by ian, except the problems are not really line noise. Just unplugging the line causes a serial line break unless you are quick enough to re-plug it in less than the break detection time, and no one can do that except at low speeds like 1 bit/second, since the break detection time is just 1 character times. Unplugging is also less of a problem than turning off the terminal, since with the former you are more likely to see that the system has entered the debugger immediately after re-plugging, instead of much later when turning on the terminal. I didn't notice this problem for many years. Even BREAK_TO_DEBUGGER was only added in 1996. Before that, serial line breaks caused debugger entry unconditionally if a debugger was configured. Just before that, until 1995 debugger entry was similarly unconditional except it occured when a slip FRAME_END character (0xc0) was received. I don't see how slip could have worked with that. I didn't notice the problem with unplugging for many more years. There was a bug in detecting these line breaks. Serial interrupts were only enabled when the console was open for normal syscalls and the line breaks were not detected otherwise, so they didn't bite as often as they should have. 3. So BREAK_TO_DEBUGGER should normally not be configured. ALT_BREAK_TO_DEBUGGER used to provide an adequate workaround. The name of this option is confusing but not wrong. I gives an alternative to entering the debugger with a serial line break, not an alternative to the normal way of breaking into the debugger. 4. Breakage started occuring with multiple consoles. You might have 1 serial console that is most secure and never turned off, so BREAK_TO_DEBUGGER is best for it, 1 serial console that is secure but sometimes turned off, so ALT_BREAK_TO_DEBUGGER is best for it, and 1 serial console that is insecure so both BREAK_TO_DEBUGGER and ALT_BREAK_TO_DEBUGGER are too insecure to use. Since they are global flags, they must be turned off for all serial consoles. Or just don't use multiple serial consoles. Since no serial console drivers support multiple serial consoles, this is too easy to do. 5. Next, the breakage with multiple consoles spread to affect all console drivers. The configuration is now dynamic, with sysctls to control it, but the confusion of serial line breaks with breaking into the debugger combined with the null support for multiple serial consoles breaks the usual case of just no serial consoles at all, as pointed out by jmg. The config-time-variable for serial line breaks (BREAK_TO_DEBUGGER) is misused to configure "breaking" into the the debugger in the usual ways (but not the ways given by ALT_BREAK_TO_DEBUGGER -- that gives security holes instead). From subr_kdb.c: X #ifdef BREAK_TO_DEBUGGER X #define KDB_BREAK_TO_DEBUGGER 1 X #else X #define KDB_BREAK_TO_DEBUGGER 0 X #endif Wrong default for usual entry from non-serial consoles. X X #ifdef ALT_BREAK_TO_DEBUGGER X #define KDB_ALT_BREAK_TO_DEBUGGER 1 X #else X #define KDB_ALT_BREAK_TO_DEBUGGER 0 X #endif Better, but it gives security holes for non-serial consoles if it is configured. X X static int kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER; X static int kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER; X ... X SYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, X CTLFLAG_RWTUN | CTLFLAG_SECURE, X &kdb_break_to_debugger, 0, "Enable break to debugger"); X X SYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, X CTLFLAG_RWTUN | CTLFLAG_SECURE, X &kdb_alt_break_to_debugger, 0, "Enable alternative break to debugger"); X ... X int X kdb_break(void) X { X X if (!kdb_break_to_debugger) X return (0); X kdb_enter(KDB_WHY_BREAK, "Break to debugger"); X return (KDB_REQ_DEBUGGER); X } Only non-alt "breaking" us limited by kdb_break_to_debugger. kdb_break() is only called from console drivers: - from serial console drivers, when a serial line break is received - from syscons, when the debugger entry key combination is pressed. Syscons still has adequate although poorly implemented security for this: - compile-time configuration by SC_DISABLE_KDBKEY (default enabled) - runtime configuration by sysctl hw.syscons.kbd_debug (default from the config option) The config option shouldn't exist, but the sysctl is needed to handle the case of needing kdb_break_to_debugger for a serial console but the syscons console being to insecure for this, since the kdb sysctl is too global. This only works since there is really only one syscons device -- different security on different vt's is not important. - vt is chummy with the implementation and bypasses some of the implementation's bugs by bypassing kdb_break(). So its debugger entry in the usual way it is only limited by its own sysctl, like syscons used to be. OTOH, vt doesn't bypass kdb_alt_break() or have its own sysctl variable to limit entry in unusual ways. Syscons uses its old SC_DISABLE_KDBKEY+hw.syscons.kbd_debug for this too. Security holes: GENERIC doesn't have either BREAK_TO_DEBUGGER or ALT_BREAK_TO_DEBUGGER, so most user configuration probably don't have either of these either. Syscons used to default to debugger entry enabled, but only normal entry was supported. This was apparently reversed by the dynamic configuration -- since *BREAK_TO_DEBUGGER is not the default, the sysctls default to disabled. Syscons grew support for alternative "breaking" at much the same time as the dynamic configuration was added. Now, if you enable ALT_BREAK_TO_DEBUGGER to use for a serial console, you get it for syscons and vt too. My workarounds for this: - I stopped configuring BREAK_TO_DEBUGGER and started always configuring ALT_BREAK_TO_DEBUGGER 10-15 years ago. Then to fix the reversal of the default for debugger keys in syscons: - in some configurations, I define KDB_BREAK_TO_DEBUGGER as 1 unconditionally in subr_kdb.c. I have to remember to either not use a serial console or not unplug it. - in most configurations, I change the sysctl for kdb_break_to_debug to 1 early in the boot, and have to remember things as above. This can be confusing. I forgot that I did this, and was confused by ddb working at first when booted with -d, and then later in multi-user mode, but not at the askroot prompt or in single user mode. (The debugger and other keys don't work right during the boot, but could be made to work better by always checking keys like -p mode does. I mainly miss scrollback early, not debugger entry. Even -p mode is affected by multiple console bugs in polled mode.) Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20150526153023.F914>