Linux-kernel mailing list archive 2000-26,: [PATCH] Anybody can overwrite almost anything...

# [PATCH] Anybody can overwrite almost anything...

Petr Vandrovec (vandrove@vc.cvut.cz)
Wed, 28 Jun 2000 18:44:57 +0200

- Messages sorted by: [ date ][ thread ][ subject ][ author ]
- Next message: Andrea Arcangeli: "Re: including linux/delay.h vs asm/delay.h"
- Previous message: Richard Gooch: "Re: closefd: closes a file of any process"

Hi,
I know that I should not do that, but... I'm copying one hdd to another
and to my surprise 'dd if=part2 of=/dev/hdd bs=1M seek=2500' did not work.
So I decided to find how to get it to work using /dev/fb0 interface (to
keep first 2.5GB of data in /dev/hdd safe).

Working command line was determined as 'dd if=part2 bs=1M seek=2500 > /dev/hdd'
(because of my glibc does not have truncate64).

Unfortunately, such commandline, when /dev/hdd is replaced with /dev/fb0,
leads to oops in fb_write :-(

This patch fixes:
(1) you can overwritte/read innocent kernel/process memory when specifying
offset in out of range for read/write from/to /dev/fb*... User oopsable...
(2) very large sizes (close to 4GB in 32bit environments) can pass through
copy_size logic unchanged... (I believe) User oopsable...
(3) pwrite did not work on /dev/fb, because of file->f_pos was updated instead
of passed *ppos... Bug...
(4) reads/writes terminated by pagefault incorrectly returned -EFAULT instead
of length of partial copy done... Anoying...

Patch was generated for 2.4.0-test3-pre1.
Best regards,
Petr Vandrovec
vandrove@vc.cvut.cz

P.S.: Alan, same patch should be applied to 2.2.x too. It applied only
with offset to 2.2.17-pre1 which I have here. If you'll not apply it
to 2.2.17-pre10, I'll send you diff which applies cleanly to
2.2.17-pre10.

P.P.S.: I know that currently llseek(fb, 4G, SEEK_SET) is equivalent
to llseek(fb, 0, SEEK_SET) on archs with 32bit unsigned long. If you
think that it is problem, tell me.

--- linux/drivers/video/fbmem.c Thu Jun 22 07:31:02 2000
+++ linux/drivers/video/fbmem.c Wed Jun 28 18:25:37 2000
@@ -292,19 +292,27 @@
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
struct fb_fix_screeninfo fix;
- char *base_addr;
- ssize_t copy_size;
if (! fb || ! info->disp)
return -ENODEV;
fb->fb_get_fix(&fix,PROC_CONSOLE(info), info);
- base_addr=info->disp->screen_base;
- copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
- if (copy_to_user(buf, base_addr+p, copy_size))
- return -EFAULT;
- *ppos += copy_size;
- return copy_size;
+ if (p >= fix.smem_len)
+ return 0;
+ if (count >= fix.smem_len)
+ count = fix.smem_len;
+ if (count + p > fix.smem_len)
+ count = fix.smem_len - p;
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->disp->screen_base;
+ count -= copy_to_user(buf, base_addr+p, count);
+ if (!count)
+ return -EFAULT;
+ *ppos += count;
+ }
+ return count;
}
static ssize_t
@@ -316,19 +324,32 @@
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
struct fb_fix_screeninfo fix;
- char *base_addr;
- ssize_t copy_size;
+ int err;
if (! fb || ! info->disp)
return -ENODEV;
fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
- base_addr=info->disp->screen_base;
- copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
- if (copy_from_user(base_addr+p, buf, copy_size))
- return -EFAULT;
- file->f_pos += copy_size;
- return copy_size;
+ if (p > fix.smem_len)
+ return -ENOSPC;
+ if (count >= fix.smem_len)
+ count = fix.smem_len;
+ err = 0;
+ if (count + p > fix.smem_len) {
+ count = fix.smem_len - p;
+ err = -ENOSPC;
+ }
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->disp->screen_base;
+ count -= copy_from_user(base_addr+p, buf, count);
+ *ppos += count;
+ err = -EFAULT;
+ }
+ if (count)
+ return count;
+ return err;
}
#ifdef CONFIG_KMOD

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

- Next message: Andrea Arcangeli: "Re: including linux/delay.h vs asm/delay.h"
- Previous message: Richard Gooch: "Re: closefd: closes a file of any process"