Commit 9cd1c67434544b1d9a4fb4a4cdec15608167a233
Committed by
Linus Torvalds
1 parent
4769a9a53b
Exists in
master
and in
39 other branches
pvr2fb: Fix oops when pseudo_palette is written
Reported by: Adrian McMenamin <adrianmcmenamin@gmail.com> This driver will oops when the pseudo_palette[] is written as u32 but not when written as u16. When written as u32, it corrupts the adjacent 'mmio_base' field of struct pvr2fb_par. Fix by using framebuffer_alloc()/release() to allocate struct fb_info and struct pvr2fb_par, and create the pseudo_palette[] as part of struct pvr2fb_par. Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 7 additions and 5 deletions Side-by-side Diff
drivers/video/pvr2fb.c
... | ... | @@ -143,6 +143,7 @@ |
143 | 143 | unsigned char is_lowres; /* Is horizontal pixel-doubling enabled? */ |
144 | 144 | |
145 | 145 | unsigned long mmio_base; /* MMIO base */ |
146 | + u32 palette[16]; | |
146 | 147 | } *currentpar; |
147 | 148 | |
148 | 149 | static struct fb_info *fb_info; |
... | ... | @@ -790,7 +791,7 @@ |
790 | 791 | fb_info->fbops = &pvr2fb_ops; |
791 | 792 | fb_info->fix = pvr2_fix; |
792 | 793 | fb_info->par = currentpar; |
793 | - fb_info->pseudo_palette = (void *)(fb_info->par + 1); | |
794 | + fb_info->pseudo_palette = currentpar->palette; | |
794 | 795 | fb_info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
795 | 796 | |
796 | 797 | if (video_output == VO_VGA) |
797 | 798 | |
... | ... | @@ -1082,14 +1083,15 @@ |
1082 | 1083 | #endif |
1083 | 1084 | size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32); |
1084 | 1085 | |
1085 | - fb_info = kzalloc(size, GFP_KERNEL); | |
1086 | + fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL); | |
1087 | + | |
1086 | 1088 | if (!fb_info) { |
1087 | 1089 | printk(KERN_ERR "Failed to allocate memory for fb_info\n"); |
1088 | 1090 | return -ENOMEM; |
1089 | 1091 | } |
1090 | 1092 | |
1091 | 1093 | |
1092 | - currentpar = (struct pvr2fb_par *)(fb_info + 1); | |
1094 | + currentpar = fb_info->par; | |
1093 | 1095 | |
1094 | 1096 | for (i = 0; i < ARRAY_SIZE(board_driver); i++) { |
1095 | 1097 | struct pvr2_board *pvr_board = board_driver + i; |
... | ... | @@ -1102,7 +1104,7 @@ |
1102 | 1104 | if (ret != 0) { |
1103 | 1105 | printk(KERN_ERR "pvr2fb: Failed init of %s device\n", |
1104 | 1106 | pvr_board->name); |
1105 | - kfree(fb_info); | |
1107 | + framebuffer_release(fb_info); | |
1106 | 1108 | break; |
1107 | 1109 | } |
1108 | 1110 | } |
... | ... | @@ -1126,7 +1128,7 @@ |
1126 | 1128 | #endif |
1127 | 1129 | |
1128 | 1130 | unregister_framebuffer(fb_info); |
1129 | - kfree(fb_info); | |
1131 | + framebuffer_release(fb_info); | |
1130 | 1132 | } |
1131 | 1133 | |
1132 | 1134 | module_init(pvr2fb_init); |