DF-4853 / evg_offsets.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /* * DF-4853 - machine-verify the struct geometry behind the evergreen_hdmi.c * enc_priv type confusion (DF-4635/DF-4828 family, evergreen sinks). * Structs verbatim from the audited tree: * - struct drm_display_mode sys/dev/drm/include/drm/drm_modes.h * - struct radeon_encoder_lvds sys/dev/drm/radeon/radeon_mode.h:381-397 * - struct radeon_encoder_atom_dig radeon_mode.h:427-445 * - struct radeon_afmt radeon_mode.h:235-240 */ #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <stddef.h> typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; struct list_head { struct list_head *next, *prev; }; typedef struct { int counter; } atomic_t; struct kref { atomic_t refcount; }; struct drm_mode_object { uint32_t id; uint32_t type; struct drm_object_properties *properties; struct kref refcount; void (*free_cb)(struct kref *kref); }; #define DRM_DISPLAY_MODE_LEN 32 enum drm_mode_status { MODE_OK=0 }; enum hdmi_picture_aspect { HDMI_PICTURE_ASPECT_NONE }; /* verbatim from sys/dev/drm/include/drm/drm_modes.h */ struct drm_display_mode { struct list_head head; struct drm_mode_object base; char name[DRM_DISPLAY_MODE_LEN]; enum drm_mode_status status; unsigned int type; int clock; int hdisplay; int hsync_start; int hsync_end; int htotal; int hskew; int vdisplay; int vsync_start; int vsync_end; int vtotal; int vscan; unsigned int flags; int width_mm; int height_mm; int crtc_clock; int crtc_hdisplay; int crtc_hblank_start; int crtc_hblank_end; int crtc_hsync_start; int crtc_hsync_end; int crtc_htotal; int crtc_hskew; int crtc_vdisplay; int crtc_vblank_start; int crtc_vblank_end; int crtc_vsync_start; int crtc_vsync_end; int crtc_vtotal; int *private; int private_flags; int vrefresh; int hsync; enum hdmi_picture_aspect picture_aspect_ratio; struct list_head export_head; }; struct backlight_device; /* verbatim from sys/dev/drm/radeon/radeon_mode.h:235-240 */ struct radeon_afmt { bool enabled; int offset; bool last_buffer_filled_status; int id; }; /* verbatim from sys/dev/drm/radeon/radeon_mode.h:427-445 */ struct radeon_encoder_atom_dig { bool linkb; bool coherent_mode; int dig_encoder; uint32_t lcd_misc; uint16_t panel_pwr_delay; uint32_t lcd_ss_id; struct drm_display_mode native_mode; struct backlight_device *bl_dev; int dpms_mode; uint8_t backlight_level; int panel_mode; struct radeon_afmt *afmt; struct r600_audio_pin *pin; int active_mst_links; }; /* verbatim from sys/dev/drm/radeon/radeon_mode.h:381-397 */ struct radeon_encoder_lvds { uint16_t panel_vcc_delay; uint8_t panel_pwr_delay; uint8_t panel_digon_delay; uint8_t panel_blon_delay; uint16_t panel_ref_divider; uint8_t panel_post_divider; uint16_t panel_fb_divider; bool use_bios_dividers; uint32_t lvds_gen_cntl; struct drm_display_mode native_mode; struct backlight_device *bl_dev; int dpms_mode; uint8_t backlight_level; }; int main(void) { printf("sizeof(drm_display_mode) = %zu\n", sizeof(struct drm_display_mode)); printf("sizeof(radeon_encoder_lvds) = %zu <- enc_priv of LCD-carrying digital encoders\n", sizeof(struct radeon_encoder_lvds)); printf("sizeof(radeon_encoder_atom_dig) = %zu <- what evergreen_hdmi.c assumes\n", sizeof(struct radeon_encoder_atom_dig)); printf("offsetof(dig, afmt) = %zu <- dig->afmt on lvds obj (evergreen_hdmi.c:431)\n", offsetof(struct radeon_encoder_atom_dig, afmt)); printf("offsetof(afmt, enabled) = %zu <- wild write target (evergreen_hdmi.c:458)\n", offsetof(struct radeon_afmt, enabled)); printf("offsetof(afmt, offset) = %zu <- wild read feeding MMIO (:438-455)\n", offsetof(struct radeon_afmt, offset)); if (offsetof(struct radeon_encoder_atom_dig, afmt) >= sizeof(struct radeon_encoder_lvds)) printf("=> dig->afmt reads %zu byte(s) PAST the 280-byte lvds object " "(280 -> 288-byte slab chunk, ZERO slack) into the ADJACENT chunk\n", offsetof(struct radeon_encoder_atom_dig, afmt) - sizeof(struct radeon_encoder_lvds)); return 0; } |