aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbmem.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index eec14d2ca1c7..ea16e654a9b6 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -717,13 +717,30 @@ static const struct file_operations fb_proc_fops = {
717 .release = seq_release, 717 .release = seq_release,
718}; 718};
719 719
720static ssize_t 720/*
721fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 721 * We hold a reference to the fb_info in file->private_data,
722 * but if the current registered fb has changed, we don't
723 * actually want to use it.
724 *
725 * So look up the fb_info using the inode minor number,
726 * and just verify it against the reference we have.
727 */
728static struct fb_info *file_fb_info(struct file *file)
722{ 729{
723 unsigned long p = *ppos;
724 struct inode *inode = file->f_path.dentry->d_inode; 730 struct inode *inode = file->f_path.dentry->d_inode;
725 int fbidx = iminor(inode); 731 int fbidx = iminor(inode);
726 struct fb_info *info = registered_fb[fbidx]; 732 struct fb_info *info = registered_fb[fbidx];
733
734 if (info != file->private_data)
735 info = NULL;
736 return info;
737}
738
739static ssize_t
740fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
741{
742 unsigned long p = *ppos;
743 struct fb_info *info = file_fb_info(file);
727 u8 *buffer, *dst; 744 u8 *buffer, *dst;
728 u8 __iomem *src; 745 u8 __iomem *src;
729 int c, cnt = 0, err = 0; 746 int c, cnt = 0, err = 0;
@@ -788,9 +805,7 @@ static ssize_t
788fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 805fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
789{ 806{
790 unsigned long p = *ppos; 807 unsigned long p = *ppos;
791 struct inode *inode = file->f_path.dentry->d_inode; 808 struct fb_info *info = file_fb_info(file);
792 int fbidx = iminor(inode);
793 struct fb_info *info = registered_fb[fbidx];
794 u8 *buffer, *src; 809 u8 *buffer, *src;
795 u8 __iomem *dst; 810 u8 __iomem *dst;
796 int c, cnt = 0, err = 0; 811 int c, cnt = 0, err = 0;
@@ -1168,10 +1183,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1168 1183
1169static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1184static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1170{ 1185{
1171 struct inode *inode = file->f_path.dentry->d_inode; 1186 struct fb_info *info = file_fb_info(file);
1172 int fbidx = iminor(inode);
1173 struct fb_info *info = registered_fb[fbidx];
1174 1187
1188 if (!info)
1189 return -ENODEV;
1175 return do_fb_ioctl(info, cmd, arg); 1190 return do_fb_ioctl(info, cmd, arg);
1176} 1191}
1177 1192
@@ -1292,12 +1307,13 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
1292static long fb_compat_ioctl(struct file *file, unsigned int cmd, 1307static long fb_compat_ioctl(struct file *file, unsigned int cmd,
1293 unsigned long arg) 1308 unsigned long arg)
1294{ 1309{
1295 struct inode *inode = file->f_path.dentry->d_inode; 1310 struct fb_info *info = file_fb_info(file);
1296 int fbidx = iminor(inode); 1311 struct fb_ops *fb;
1297 struct fb_info *info = registered_fb[fbidx];
1298 struct fb_ops *fb = info->fbops;
1299 long ret = -ENOIOCTLCMD; 1312 long ret = -ENOIOCTLCMD;
1300 1313
1314 if (!info)
1315 return -ENODEV;
1316 fb = info->fbops;
1301 switch(cmd) { 1317 switch(cmd) {
1302 case FBIOGET_VSCREENINFO: 1318 case FBIOGET_VSCREENINFO:
1303 case FBIOPUT_VSCREENINFO: 1319 case FBIOPUT_VSCREENINFO:
@@ -1330,16 +1346,18 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
1330static int 1346static int
1331fb_mmap(struct file *file, struct vm_area_struct * vma) 1347fb_mmap(struct file *file, struct vm_area_struct * vma)
1332{ 1348{
1333 int fbidx = iminor(file->f_path.dentry->d_inode); 1349 struct fb_info *info = file_fb_info(file);
1334 struct fb_info *info = registered_fb[fbidx]; 1350 struct fb_ops *fb;
1335 struct fb_ops *fb = info->fbops;
1336 unsigned long off; 1351 unsigned long off;
1337 unsigned long start; 1352 unsigned long start;
1338 u32 len; 1353 u32 len;
1339 1354
1355 if (!info)
1356 return -ENODEV;
1340 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 1357 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1341 return -EINVAL; 1358 return -EINVAL;
1342 off = vma->vm_pgoff << PAGE_SHIFT; 1359 off = vma->vm_pgoff << PAGE_SHIFT;
1360 fb = info->fbops;
1343 if (!fb) 1361 if (!fb)
1344 return -ENODEV; 1362 return -ENODEV;
1345 mutex_lock(&info->mm_lock); 1363 mutex_lock(&info->mm_lock);