console.c: scrolling bug found

Riku Saikkonen (rjs@isil.lloke.dna.fi)
Wed, 14 Feb 1996 23:24:43 +0200


[copy posted to comp.os.linux.development.system]

I wanted to do some very minor kernel hacking, and thought I'd look at the
slight scrolling bug that's been present ever since 0.something... And, sure
enough, I found it; or at least I think I did. I'm talking about the bug
that causes one frame of a corrupt display every now and then (rarely)
during heavy scrolling.

Here's __set_origin() from console.c (from kernel 1.2.13), the function that
does the actual hardware scroll (change of screen origin in video memory)
after the video memory has been appropriately updated:

static inline void __set_origin(unsigned short offset)
{
unsigned long flags;

clear_selection();

save_flags(flags); cli();
__origin = offset;
outb_p(12, video_port_reg);
outb_p(offset >> 8, video_port_val);
outb_p(13, video_port_reg);
outb_p(offset, video_port_val);
restore_flags(flags);
}

The hw scroll is done by four outb_p()s. The bug, I think, is shown when the
display is being refreshed during these outb_p()s. Between the second and
fourth outb_p(), if the old and new high bytes are different, the origin of
the screen is set at an invalid value (the low byte has changed, the high
byte has not), and thus the text to be written to the screen is taken from
the wrong part of display memory.

This causes the occasional incorrect display in one frame (it is fixed when
the video card does the next display refresh since the outb_p()s have then
been completed). I guess console switching and scrollback could also cause
the same, but the bug happening is so rare that it has only been noticed in
scrolling (since systems usually do a lot of scrolling).

The cli() at the start doesn't help, because it doesn't stop the constant
refreshing of the display done in the display adapter's hardware.

The only way that I can think of to fix this would be to wait until the
vertical sync pulse is active (and thus the display adapter isn't doing a
refresh) before those outb_p()s. But this would slow down scrolling quite a
lot, so to make it effective we'd have to buffer the scrolls and scroll
several lines in one __set_origin(). And that is quite a lot of work to fix
such a small bug...

So, I guess it's reasonable to leave this slight glitch in, since it's so
harmless...

In theory it could be a security hole since a console user might happen to
view sensitive information happening to still be in the incorrectly
displayed part of video memory, but it is very improbable that this will
happen in practice.

--
-=- Rjs -=- rjs@spider.compart.fi - http://isil.lloke.dna.fi/rjs/