Re: Dealing with the NMI mess

From: Maciej W. Rozycki
Date: Tue Sep 08 2015 - 12:21:43 EST


On Mon, 7 Sep 2015, Andy Lutomirski wrote:

> > It does not have to be mentioned, because it's implied by how the #DB
> > exception is propagated: regardless of its origin it never checks the DPL.
> > And user-mode software may well use POPF at any time to set the TF bit in
> > the flags register to the same effect, so the OS needs to be prepared for
> > a #DB exception it hasn't scheduled itself anyway.
>
> Not really.
>
> int $1 checks DPL. Setting TF results in saved TF set and the
> corresponding bit in DR6 set as well. Triggering a #DB using the
> debug registers requires active OS help.

INT $1 is a software interrupt instruction, it does not trigger a #DB.
Similarly INT $13 checks DPL while #GP does not. Or maybe INT $6 vs UD2
is a better analogy; the latter is as much INT6 as the 0xf1 encoding is
INT1.

Yes, you'll get a DR6 status with no new bits set. So what? You can
ignore it and IRET with no adverse effects. You can print diagnostics if
you're pedantic. You can kill the offending user program, but that's no
harm, because it already did the undefined. None of these is an issue,
and certainly not one for security.

Panicking OTOH would be, but that would IMHO be a silly choice and a bad
OS design. You never need to crash due to a user-mode exception, even an
unknown one. What if you run on a new CPU which has a new user-mode
exception unknown at the time the OS binary was compiled? That's an
analogous situation for an architecture like x86 where strict backwards
compatibility is maintained.

A reasonable #DB handler will do something like:

{
int dr6 = read_dr6();

write_dr6(0);
if (dr6 & DR6_MASK_X)
handle_dr6_x();
if (dr6 & DR6_MASK_Y)
handle_dr6_y();
/* Etc... */

return;
}

and will work just fine where invoked with no bits set in DR6.

> So operating systems need to handle a #DB without no indicated cause
> without spewing warnings or crashing, and there is no indication
> whatsoever in the SDM or APM that this is the case.

Strictly speaking the SDM does not state that at least one status bit
shall be set in DR6 either.

FAOD I'm not saying of course that documenting INT1 as a model-specific
instruction encoding reserved for #DB generation or stating something to
the effect that the OS is required to handle (e.g. discard) a #DB
exception seen with no status bits set in DR6 would be bad. No, it would
certainly be nice. But I maintain that I don't see it as strictly
necessary.

Pester Intel if you disagree, I'm not the right person to complain about
it anyway. ;)

Maciej
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/