/dev/mem: dont allow seek to last page
authorWu Fengguang <fengguang.wu@intel.com>
Wed, 10 Mar 2010 23:21:51 +0000 (15:21 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Mar 2010 23:52:35 +0000 (15:52 -0800)
So as to return a uniform error -EOVERFLOW instead of a random one:

# kmem-seek 0xfffffffffffffff0
seek /dev/kmem: Device or resource busy
# kmem-seek 0xfffffffffffffff1
seek /dev/kmem: Block device required

Suggested by OGAWA Hirofumi.

Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/mem.c

index 48788db4e280f89e289a4d9f2e31b8519244b82c..e3f5577cbce3c2cf2e14b938f1e930294dd9d3e7 100644 (file)
@@ -708,16 +708,23 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
 
        mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
        switch (orig) {
-               case 0:
+               case SEEK_CUR:
+                       offset += file->f_pos;
+                       if ((unsigned long long)offset <
+                           (unsigned long long)file->f_pos) {
+                               ret = -EOVERFLOW;
+                               break;
+                       }
+               case SEEK_SET:
+                       /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */
+                       if ((unsigned long long)offset >= ~0xFFFULL) {
+                               ret = -EOVERFLOW;
+                               break;
+                       }
                        file->f_pos = offset;
                        ret = file->f_pos;
                        force_successful_syscall_return();
                        break;
-               case 1:
-                       file->f_pos += offset;
-                       ret = file->f_pos;
-                       force_successful_syscall_return();
-                       break;
                default:
                        ret = -EINVAL;
        }