fbdev: color map copying bounds checking
Subsystems (2)
PATCH 1/1 fbdev: color map copying bounds checking
Copying color maps to userspace doesn't check the value of to->start, which will cause kernel heap buffer OOB read due to signedness wraps.
CVE-2016-8405
Reported-by Peter Pi (@heisecode) of Trend Micro
Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by Kees Cook <[email protected]>
--- drivers/video/fbdev/core/fbcmap.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
drivers/video/fbdev/core/fbcmap.c +14 -12
@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)int fb_copy_cmap (const struct fb_cmap *from,struct fb_cmap *to) { -int tooff =0 , fromoff =0 ; -int size; +unsigned int tooff =0 , fromoff =0 ; +size_t size;if (to->start > from->start) fromoff = to->start - from->start;else tooff = from->start - to->start; - size = to->len - tooff; -if (size > (int ) (from->len - fromoff)) - size = from->len - fromoff; -if (size <=0 ) +if (fromoff >= from->len || tooff >= to->len) +return -EINVAL ; + + size =min_t (size_t, to->len - tooff, from->len - fromoff); +if (size =0 )return -EINVAL ; size *=sizeof (u16);
@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)int fb_cmap_to_user (const struct fb_cmap *from,struct fb_cmap_user *to) { -int tooff =0 , fromoff =0 ; -int size; +unsigned int tooff =0 , fromoff =0 ; +size_t size;if (to->start > from->start) fromoff = to->start - from->start;else tooff = from->start - to->start; - size = to->len - tooff; -if (size > (int ) (from->len - fromoff)) - size = from->len - fromoff; -if (size <=0 ) +if (fromoff >= from->len || tooff >= to->len) +return -EINVAL ; + + size =min_t (size_t, to->len - tooff, from->len - fromoff); +if (size =0 )return -EINVAL ; size *=sizeof (u16);
Signature · 6 lines
2.7.4 -- Kees Cook Nexus Security
Hi again,
It's been two weeks with no response. This fixes a kernel heap OOB read. Andrew, can you take this into -mm?
-Kees
Quoted 74 lines · Kees Cook
Copying color maps to userspace doesn't check the value of
to->start, which will cause kernel heap buffer OOB read due to signedness wraps.CVE-2016-8405
Reported-by Peter Pi (@heisecode) of Trend MicroFixes 1da177e4c3f4 ("Linux-2.6.12-rc2")Signed-off-by Kees Cook <[email protected]>--- drivers/video/fbdev/core/fbcmap.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)drivers/video/fbdev/core/fbcmap.c +14
-13@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)int fb_copy_cmap (const struct fb_cmap *from,struct fb_cmap *to) { -int tooff =0 , fromoff =0 ; -int size; +unsigned int tooff =0 , fromoff =0 ; +size_t size;if (to->start > from->start) fromoff = to->start - from->start;else tooff = from->start - to->start; - size = to->len - tooff; -if (size > (int ) (from->len - fromoff)) - size = from->len - fromoff; -if (size <=0 ) +if (fromoff >= from->len || tooff >= to->len) +return -EINVAL ; + + size =min_t (size_t, to->len - tooff, from->len - fromoff); +if (size =0 )return -EINVAL ; size *=sizeof (u16);@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)int fb_cmap_to_user (const struct fb_cmap *from,struct fb_cmap_user *to) { -int tooff =0 , fromoff =0 ; -int size; +unsigned int tooff =0 , fromoff =0 ; +size_t size;if (to->start > from->start) fromoff = to->start - from->start;else tooff = from->start - to->start; - size = to->len - tooff; -if (size > (int ) (from->len - fromoff)) - size = from->len - fromoff; -if (size <=0 ) +if (fromoff >= from->len || tooff >= to->len) +return -EINVAL ; + + size =min_t (size_t, to->len - tooff, from->len - fromoff); +if (size =0 )return -EINVAL ; size *=sizeof (u16); --2.7.4
--
Kees Cook
Nexus Security
Signature · 2 lines
Kees Cook Nexus Security