132 lines · 2.9 KB · C
RawDownload
/* * linux/drivers/video/fb_sys_read.c - Generic file operations where * framebuffer is in system RAM * * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. * */ #include <linux/export.h>#include <linux/fb.h>#include <linux/module.h>#include <linux/uaccess.h> ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,		    loff_t *ppos){	unsigned long p = *ppos;	void *src;	int err = 0;	unsigned long total_size, c;	ssize_t ret; 	if (!(info->flags & FBINFO_VIRTFB))		fb_warn_once(info, "Framebuffer is not in virtual address space."); 	if (!info->screen_buffer)		return -ENODEV; 	total_size = info->screen_size; 	if (total_size == 0)		total_size = info->fix.smem_len; 	/*	 * Security Hardening: Defend against buggy legacy drivers that may	 * calculate a malformed screen_size. Clamp total_size to the actual	 * hardware mapped memory limit (smem_len) to prevent OOB access.	 */	if (info->fix.smem_len && total_size > info->fix.smem_len)		total_size = info->fix.smem_len; 	if (p >= total_size)		return 0; 	if (count >= total_size)		count = total_size; 	if (count + p > total_size)		count = total_size - p; 	src = info->screen_buffer + p; 	if (info->fbops->fb_sync)		info->fbops->fb_sync(info); 	c = copy_to_user(buf, src, count);	if (c)		err = -EFAULT;	ret = count - c; 	*ppos += ret; 	return ret ? ret : err;}EXPORT_SYMBOL_GPL(fb_sys_read); ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,		     size_t count, loff_t *ppos){	unsigned long p = *ppos;	void *dst;	int err = 0;	unsigned long total_size, c;	size_t ret; 	if (!(info->flags & FBINFO_VIRTFB))		fb_warn_once(info, "Framebuffer is not in virtual address space."); 	if (!info->screen_buffer)		return -ENODEV; 	total_size = info->screen_size; 	if (total_size == 0)		total_size = info->fix.smem_len; 	/*	 * Security Hardening: Defend against buggy legacy drivers that may	 * calculate a malformed screen_size. Clamp total_size to the actual	 * hardware mapped memory limit (smem_len) to prevent OOB access.	 */	if (info->fix.smem_len && total_size > info->fix.smem_len)		total_size = info->fix.smem_len; 	if (p > total_size)		return -EFBIG; 	if (count > total_size) {		err = -EFBIG;		count = total_size;	} 	if (count + p > total_size) {		if (!err)			err = -ENOSPC; 		count = total_size - p;	} 	dst = info->screen_buffer + p; 	if (info->fbops->fb_sync)		info->fbops->fb_sync(info); 	c = copy_from_user(dst, buf, count);	if (c)		err = -EFAULT;	ret = count - c; 	*ppos += ret; 	return ret ? ret : err;}EXPORT_SYMBOL_GPL(fb_sys_write); MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");MODULE_DESCRIPTION("Generic file read (fb in system RAM)");MODULE_LICENSE("GPL");