[PATCH] Avoid segfaults in XF86VidMode GammaRamp functions if randr_crtc is NULL

Alan Coopersmith Alan.Coopersmith at Sun.COM
Tue Jan 26 23:31:55 PST 2010


Keith Packard wrote:
> On Tue, 26 Jan 2010 22:25:04 -0800, Alan Coopersmith <alan.coopersmith at sun.com> wrote:
> 
>> Fixes crash when xscreensaver tries to use GammaRamp calls to fade out
>> http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6915712
> 
> This seems odd to me; how can you have a crtc and no randr_crtc?

Unfortunately, I don't have the source to the driver used when this was hit
(another engineer here does have it if it helps).  I know it's based on the
xf86-video-radeon driver, but modified to work with the SPARC kernel fb driver
for the ATI boards Sun OEM'ed.   (Someday I'd love to get ATI's permission to
merge our changes back to the radeon driver, but unfortunately our license
predate ATI's acceptance of open source drivers.)

What I saw in the debugger was:

t at 1 (l at 1) signal SEGV (no mapping at the fault address) in xf86GetGammaRampSize
at line 1080 in file "xf86cmap.c"
 1078           RRCrtcPtr crtc =
config->output[config->compat_output]->crtc->randr_crtc;
 1079
 1080           return crtc->gammaSize;

(dbx) where
current thread: t at 1
=>[1] xf86GetGammaRampSize(pScreen = 0x100868120), line 1080 in "xf86cmap.c"
  [2] VidModeGetGammaRampSize(scrnIndex = 0), line 522 in "xf86VidMode.c"
  [3] ProcXF86VidModeGetGammaRampSize(0x10092e950, 0xffffffff7bb0cef8, 0x10df64,
0x148, 0x0, 0xffffffff7bc1ab98), at 0xffffffff7bb0cca4
  [4] Dispatch(0x4333b0, 0x1008229f8, 0x10092e950, 0x0, 0x10092ecb0, 0xbe0), at
0x100065c00
  [5] main(0x8, 0xffffffff7ffffba8, 0x100825250, 0x100822a00, 0x100825248,
0x100819f88), at 0x1000c7c2c

(dbx) print crtc
crtc = (nil)
(dbx) print config->output
config->output = 0x100842190
(dbx) print config->compat_output
config->compat_output = 1
(dbx) print config->output[config->compat_output]
config->output[config->compat_output] = 0x10085c320
(dbx) print config->output[config->compat_output]->crtc
config->output[config->compat_output]->crtc = 0x100859fc0
(dbx) print *config->output[config->compat_output]->crtc
*config->output[config->compat_output]->crtc = {
    version                 = 3
    scrn                    = 0x1008542a0
    enabled                 = 1
    mode                    = {
        prev            = (nil)
        next            = 0x10085d090
        name            = 0x1008421f0 "VESA_STD_1280x1024x75"
        status          = MODE_OK
        type            = 136
        Clock           = 135000
        HDisplay        = 1280
        HSyncStart      = 1296
        HSyncEnd        = 1440
        HTotal          = 1688
        HSkew           = 0
        VDisplay        = 1024
        VSyncStart      = 1025
        VSyncEnd        = 1028
        VTotal          = 1066
        VScan           = 0
        Flags           = 5
        ClockIndex      = 0
        SynthClock      = 0
        CrtcHDisplay    = 1280
        CrtcHBlankStart = 1280
        CrtcHSyncStart  = 1296
        CrtcHSyncEnd    = 1440
        CrtcHBlankEnd   = 1688
        CrtcHTotal      = 1688
        CrtcHSkew       = 0
        CrtcVDisplay    = 1024
        CrtcVBlankStart = 1024
        CrtcVSyncStart  = 1025
        CrtcVSyncEnd    = 1028
        CrtcVBlankEnd   = 1066
        CrtcVTotal      = 1066
        CrtcHAdjusted   = 0
        CrtcVAdjusted   = 0
        PrivSize        = 0
        Private         = (nil)
        PrivFlags       = 0
        HSync           = 0.0
        VRefresh        = 75.02467
    }
    rotation                = 1U
    rotatedPixmap           = (nil)
    rotatedData             = (nil)
    x                       = 0
    y                       = 0
    desiredMode             = {
        prev            = (nil)
        next            = 0x10085d090
        name            = 0x1008421f0 "VESA_STD_1280x1024x75"
        status          = MODE_OK
        type            = 136
        Clock           = 135000
        HDisplay        = 1280
        HSyncStart      = 1296
        HSyncEnd        = 1440
        HTotal          = 1688
        HSkew           = 0
        VDisplay        = 1024
        VSyncStart      = 1025
        VSyncEnd        = 1028
        VTotal          = 1066
        VScan           = 0
        Flags           = 5
        ClockIndex      = 0
        SynthClock      = 0
        CrtcHDisplay    = 1280
        CrtcHBlankStart = 1280
        CrtcHSyncStart  = 1296
        CrtcHSyncEnd    = 1440
        CrtcHBlankEnd   = 1688
        CrtcHTotal      = 1688
        CrtcHSkew       = 0
        CrtcVDisplay    = 1024
        CrtcVBlankStart = 1024
        CrtcVSyncStart  = 1025
        CrtcVSyncEnd    = 1028
        CrtcVBlankEnd   = 1066
        CrtcVTotal      = 1066
        CrtcHAdjusted   = 0
        CrtcVAdjusted   = 0
        PrivSize        = 0
        Private         = (nil)
        PrivFlags       = 0
        HSync           = 0.0
        VRefresh        = 75.02467
    }
    desiredRotation         = 1U
    desiredX                = 0
    desiredY                = 0
    funcs                   = 0xffffffff7af6b8c0
    driver_private          = 0x10085aa90
    randr_crtc              = (nil)
    cursor_argb             = 0
    cursor_in_range         = 1
    cursor_shown            = 0
    crtc_to_framebuffer     = {
        matrix = (
(65536, 0, 0)
(0, 65536, 0)
(0, 0, 65536)

)
    }
    f_crtc_to_framebuffer   = {
        m = (
(1.0, 0.0, 0.0)
(0.0, 1.0, 0.0)
(0.0, 0.0, 1.0)

)
    }
    f_framebuffer_to_crtc   = {
        m = (
(1.0, 0.0, 0.0)
(0.0, 1.0, 0.0)
(0.0, 0.0, 1.0)

)
    }
    filter                  = (nil)
    params                  = (nil)
    nparams                 = 0
    filter_width            = 0
    filter_height           = 0
    transform_in_use        = 0
    transform               = {
        transform   = {
            matrix = (
(0, 0, 0)
(0, 0, 0)
(0, 0, 0)

)
        }
        f_transform = {
            m = (
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)

)
        }
        f_inverse   = {
            m = (
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)

)
        }
        filter      = (nil)
        params      = (nil)
        nparams     = 0
        width       = 0
        height      = 0
    }
    transformPresent        = 0
    desiredTransform        = {
        transform   = {
            matrix = (
(0, 0, 0)
(0, 0, 0)
(0, 0, 0)

)
        }
        f_transform = {
            m = (
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)

)
        }
        f_inverse   = {
            m = (
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)
(0.0, 0.0, 0.0)

)
        }
        filter      = (nil)
        params      = (nil)
        nparams     = 0
        width       = 0
        height      = 0
    }
    desiredTransformPresent = 0
    bounds                  = {
        x1 = 0
        y1 = 0
        x2 = 1280
        y2 = 1024
    }
    panningTotalArea        = {
        x1 = 0
        y1 = 0
        x2 = 0
        y2 = 0
    }
    panningTrackingArea     = {
        x1 = 0
        y1 = 0
        x2 = 0
        y2 = 0
    }
    panningBorder           = (0, 0, 0, 0)
    gamma_red               = 0x10085a480
    gamma_green             = 0x10085a680
    gamma_blue              = 0x10085a880
    gamma_size              = 256
    active                  = 1
    shadowClear             = 0
}
(dbx) print *config->output[config->compat_output]->crtc->funcs
*config->output[config->compat_output]->crtc->funcs = {
    dpms                = 0xffffffff7ae3b908 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_dpms()
    save                = (nil)
    restore             = (nil)
    lock                = 0xffffffff7ae3cce4 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_lock()
    unlock              = 0xffffffff7ae3cd28 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_unlock()
    mode_fixup          = 0xffffffff7ae3ba00 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_mode_fixup()
    prepare             = 0xffffffff7ae3ba20 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_mode_prepare()
    mode_set            = 0xffffffff7ae3c000 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_mode_set()
    commit              = 0xffffffff7ae3c058 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_mode_commit()
    gamma_set           = 0xffffffff7ae3c518 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_gamma_set()
    shadow_allocate     = 0xffffffff7ae3cdf0 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_shadow_allocate()
    shadow_create       = 0xffffffff7ae3cfb8 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_shadow_create()
    shadow_destroy      = 0xffffffff7ae3d070 =
&`efb_drv.so`radeon_crtc.c`radeon_crtc_shadow_destroy()
    set_cursor_colors   = 0xffffffff7ae1919c = &radeon_crtc_set_cursor_colors()
    set_cursor_position = 0xffffffff7ae18fac = &radeon_crtc_set_cursor_position()
    show_cursor         = 0xffffffff7ae18e6c = &radeon_crtc_show_cursor()
    hide_cursor         = 0xffffffff7ae18f10 = &radeon_crtc_hide_cursor()
    load_cursor_image   = (nil)
    load_cursor_argb    = 0xffffffff7ae19304 = &radeon_crtc_load_cursor_argb()
    destroy             = (nil)
    set_mode_major      = (nil)
    set_origin          = (nil)
}

I was only able to reproduce on a configuration with two cards running in
Xinerama mode.   Could this be another instance of RandR & Xinerama not
playing nicely together?

>> @@ -1077,7 +1079,8 @@ xf86GetGammaRampSize(ScreenPtr pScreen)
>>  	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
>>  	RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
>>  
>> -	return crtc->gammaSize;
>> +	if (crtc)
>> +	    return crtc->gammaSize;
> 
> Uh, what's the return value if you don't have a crtc?

In that case it would fall throw to the code that handles the
cases when xf86_crtc_supports_gamma(pScrn) returns false.

-- 
	-Alan Coopersmith-           alan.coopersmith at sun.com
	 Sun Microsystems, Inc. - X Window System Engineering



More information about the xorg-devel mailing list