summaryrefslogtreecommitdiff
path: root/drivers/char/mem.c
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2010-03-10 15:21:51 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 15:52:35 -0800
commitdcefafb6ac90ece8d68a6c203105f3d313e52da4 (patch)
treec0aad5b135dc95f2aaa8d3c089a1ac44144ef424 /drivers/char/mem.c
parent2cb9a75d13676d75bcc6fbc6f885403795581913 (diff)
/dev/mem: dont allow seek to last page
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>
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r--drivers/char/mem.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 48788db4e280..e3f5577cbce3 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -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;
}