[PATCH] Fixing panic in vt_fb_blank() if fb_size is not a multiple of fb_stride
Andre Albsmeier
andre at fbsd.ata.myota.org
Thu Jan 1 19:27:28 UTC 2015
[Crossposting to -hackers and -x11 as this is vt and i915kms related]
I can reliably crash an older notebook (Fujitsu E8310) with Intel
graphics (GM965) by loading i915kms after having booted but only
if vt(4) is used instead of old syscons.
Reason for the crash is a page fault in vt_fb_blank() which is
in /sys/dev/vt/hw/fb/vt_fb.c:
#7 0xc08c929e in bcopy () at /src/src-9/sys/i386/i386/support.s:198
#8 0xc08d93e0 in memmove (dest=0xedfd3c00, src=0xeda30000, n=5632) at /src/src-9/sys/libkern/memmove.c:36
#9 0xc053fac7 in vt_fb_mem_copy (sc=0xc6919500, offset_to=5913600, offset_from=0, size=5632) at /src/src-9/sys/dev/fb/fbd.c:205
#10 0xc060370e in vt_fb_blank (vd=0xc09c3c40, color=<value optimized out>) at /src/src-9/sys/dev/vt/hw/fb/vt_fb.c:179
#11 0xc0603b10 in vt_fb_init (vd=0xc09c3c40) at /src/src-9/sys/dev/vt/hw/fb/vt_fb.c:306
#12 0xc06098db in vt_allocate (drv=0xc09c3b80, softc=0xc6919500) at /src/src-9/sys/dev/vt/vt_core.c:1970
in vt_fb_blank() we find:
for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) {
info->copy(info, o, 0, info->fb_stride);
}
fb_size gets calculated in intelfb_create() which is in
/sys/dev/drm2/i915/intel_fb.c as
size = mode_cmd.pitches[0] * mode_cmd.height;
size = roundup2(size, PAGE_SIZE);
with fb_stride being the result of
mode_cmd.pitches[0] = roundup2( (mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64);
So with my funky resolution of 1400 x 1050 @32bit we get
fb_stride = 5632
fb_size = 5914624
We see that fb_stride won't fit into fb_size in whole numbers
(5914624 / 5632 = 1050.18181818181818181818) so this is why
the loop runs beyond fb_size and gives a page fault.
I am now using this modified loop in vt_fb_blank() which does
not try to run to the end of the fb by replacing
info->fb_size
by
info->fb_height * info->fb_stride
for (o = info->fb_stride; o < info->fb_height * info->fb_stride; o += info->fb_stride) {
info->copy(info, o, 0, info->fb_stride);
}
All this is on 9.3-STABLE. I have no idea if this is the correct
solution but at least I can use vt instead of sc on this notebook.
-Andre
More information about the freebsd-hackers
mailing list