Commit 6254ea38 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: fix kernel panic from FBIO_CURSOR ioctl

1. This fixes a kernel oops when issuing an FBIO_CURSOR ioctl if struct
   fb_cursor_user is filled with zero/NULLs.  Reported by Yuval Kogman
   <nothingmuch@woobling.org>.

2. This also fixes the cursor corruption in soft_cursor when
   sprite.scan_align != 1.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 12a88695
...@@ -974,7 +974,7 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite) ...@@ -974,7 +974,7 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
{ {
struct fb_cursor_user cursor_user; struct fb_cursor_user cursor_user;
struct fb_cursor cursor; struct fb_cursor cursor;
char *data = NULL, *mask = NULL; char *data = NULL, *mask = NULL, *info_mask = NULL;
u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL; u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
int err = -EINVAL; int err = -EINVAL;
...@@ -982,12 +982,12 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite) ...@@ -982,12 +982,12 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
return -EFAULT; return -EFAULT;
memcpy(&cursor, &cursor_user, sizeof(cursor_user)); memcpy(&cursor, &cursor_user, sizeof(cursor_user));
cursor.mask = NULL; cursor.mask = info->cursor.mask;
cursor.image.data = NULL; cursor.image.data = info->cursor.image.data;
cursor.image.cmap.red = NULL; cursor.image.cmap.red = info->cursor.image.cmap.red;
cursor.image.cmap.green = NULL; cursor.image.cmap.green = info->cursor.image.cmap.green;
cursor.image.cmap.blue = NULL; cursor.image.cmap.blue = info->cursor.image.cmap.blue;
cursor.image.cmap.transp = NULL; cursor.image.cmap.transp = info->cursor.image.cmap.transp;
cursor.data = NULL; cursor.data = NULL;
if (cursor.set & FB_CUR_SETCUR) if (cursor.set & FB_CUR_SETCUR)
...@@ -1047,6 +1047,8 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite) ...@@ -1047,6 +1047,8 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
cursor.image.data = data; cursor.image.data = data;
cursor.mask = mask; cursor.mask = mask;
info_mask = (char *) info->cursor.mask;
info->cursor.mask = mask;
} }
info->cursor.set = cursor.set; info->cursor.set = cursor.set;
info->cursor.rop = cursor.rop; info->cursor.rop = cursor.rop;
...@@ -1058,6 +1060,8 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite) ...@@ -1058,6 +1060,8 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
kfree(green); kfree(green);
kfree(blue); kfree(blue);
kfree(transp); kfree(transp);
if (info_mask)
info->cursor.mask = info_mask;
return err; return err;
} }
......
...@@ -22,7 +22,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -22,7 +22,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
unsigned int scan_align = info->sprite.scan_align - 1; unsigned int scan_align = info->sprite.scan_align - 1;
unsigned int buf_align = info->sprite.buf_align - 1; unsigned int buf_align = info->sprite.buf_align - 1;
unsigned int i, size, dsize, s_pitch, d_pitch; unsigned int i, size, dsize, s_pitch, d_pitch;
u8 *dst, src[64]; struct fb_cursor *cur;
u8 *dst, *src;
if (cursor->set & FB_CUR_SETSIZE) { if (cursor->set & FB_CUR_SETSIZE) {
info->cursor.image.height = cursor->image.height; info->cursor.image.height = cursor->image.height;
...@@ -48,9 +49,17 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -48,9 +49,17 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
info->cursor.image.depth = cursor->image.depth; info->cursor.image.depth = cursor->image.depth;
} }
info->cursor.image.data = cursor->image.data;
if (info->state != FBINFO_STATE_RUNNING) if (info->state != FBINFO_STATE_RUNNING)
return 0; return 0;
src = kmalloc(64 + sizeof(struct fb_cursor), GFP_ATOMIC);
if (!src)
return -ENOMEM;
cur = (struct fb_cursor *) (src + 64);
*cur = info->cursor;
s_pitch = (info->cursor.image.width + 7) >> 3; s_pitch = (info->cursor.image.width + 7) >> 3;
dsize = s_pitch * info->cursor.image.height; dsize = s_pitch * info->cursor.image.height;
d_pitch = (s_pitch + scan_align) & ~scan_align; d_pitch = (s_pitch + scan_align) & ~scan_align;
...@@ -79,9 +88,12 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -79,9 +88,12 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
else else
fb_sysmove_buf_aligned(info, &info->sprite, dst, d_pitch, src, fb_sysmove_buf_aligned(info, &info->sprite, dst, d_pitch, src,
s_pitch, info->cursor.image.height); s_pitch, info->cursor.image.height);
info->cursor.image.data = dst; cur->image.data = dst;
info->fbops->fb_imageblit(info, &info->cursor.image); info->fbops->fb_imageblit(info, &cur->image);
kfree(src);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment