⬢ DragonFlyBSD Kernel Audit
DF-3943 / interlace_sim.c
← back to finding ↓ download raw
/*
 * interlace_sim.c - userland simulation of the INTERLACE dst.height
 * mutation in resource_build_scaling_params()
 * (sys/dev/drm/amd/display/dc/core/dc_resource.c:1118-1189)
 *
 * Reproduces, in plain C, the exact control flow:
 *   entry:  if (INTERLACE) stream->dst.height *= 2;      [:1118-1119]
 *   ...     calculate_scaling_ratios(); calculate_viewport();
 *   fail:   if (viewport.h < 16 || viewport.w < 16) return false;   [:1125-1126]
 *   ...     (success path) ...
 *   exit:   if (INTERLACE) stream->dst.height /= 2;      [:1188-1189]
 *
 * The kernel executes this against the SHARED, refcounted
 * struct dc_stream_state that outlives the failed validation.
 * Each failed validation attempt leaves dst.height doubled.
 *
 * Build: cc -O2 -o interlace_sim interlace_sim.c
 * Run:   ./interlace_sim
 */
#include <stdio.h>
#include <stdbool.h>

struct rect { int x, y, width, height; };
struct stream_state { struct rect dst; bool interlace; int viewport_h, viewport_w; };

/* verbatim control flow of resource_build_scaling_params() */
static bool resource_build_scaling_params(struct stream_state *stream)
{
    if (stream->interlace)
        stream->dst.height *= 2;                    /* dc_resource.c:1118-1119 */

    /* calculate_scaling_ratios()/calculate_viewport() results summarized
     * by stream->viewport_{h,w}; a small plane (src_rect < 16px after
     * scaling into the viewport) yields viewport < 16 => validation fail */
    if (stream->viewport_h < 16 || stream->viewport_w < 16)
        return false;                               /* dc_resource.c:1125-1126 -- /=2 SKIPPED */

    /* ... taps, inits ... success path ... */

    if (stream->interlace)
        stream->dst.height /= 2;                    /* dc_resource.c:1188-1189 */
    return true;
}

int main(void)
{
    struct stream_state s = { .dst = { 0, 0, 1920, 1080 },
                              .interlace = true,
                              .viewport_h = 8, .viewport_w = 8 };
    int i;

    printf("persistent dc_stream_state.dst.height over repeated FAILED "
           "interlaced validations (1080p interlaced + tiny plane):\n");
    printf("attempt 0: dst.height=%d\n", s.dst.height);
    for (i = 1; i <= 23; i++) {
        bool ok = resource_build_scaling_params(&s);
        printf("attempt %d: %s dst.height=%d (0x%x)\n",
               i, ok ? "OK  " : "FAIL", s.dst.height, s.dst.height);
    }
    printf("\nEvery failed attempt leaves the doubling unbalanced "
           "(early return at :1125 skips the /=2 at :1188).\n");
    printf("dst.height overflows signed int after 21 doublings "
           "(1080 * 2^21 > INT_MAX) -> negative heights feed "
           "calculate_recout()/calculate_scaling_ratios().\n");
    return 0;
}