verify_area(...) possible problem.

Richard B. Johnson (root@chaos.analogic.com)
Mon, 12 Apr 1999 15:11:15 -0400 (EDT)


If I deliberately pass the kernel a bad pointer for an ioctl(), and
the kernel code does a verify_area(), the return value may be zero,
but dereferencing that pointer can cause a kernel Oops.

This was uncovered in some exhaustive testing of a driver that works
if bad parameters are not passed.

Apr 12 14:52:58 chaos kernel: Calling verify_area(VERIFY_WRITE, 12345678, 4
Apr 12 14:52:58 chaos kernel: Result was 0
Apr 12 14:52:58 chaos kernel: Unable to handle kernel paging request at virtual address 12345678
Apr 12 14:52:58 chaos kernel: current->tss.cr3 = 081a4000, %cr3 = 081a4000
Apr 12 14:52:58 chaos kernel: *pde = 00000000
Apr 12 14:52:58 chaos kernel: Oops: 0002
Apr 12 14:52:58 chaos kernel: CPU: 0
Apr 12 14:52:58 chaos kernel: EIP: 0010:[<d404920b>]
Apr 12 14:52:58 chaos kernel: EFLAGS: 00010046
Apr 12 14:52:58 chaos kernel: eax: 00000000 ebx: 00000000 ecx: 00000005 edx: c90aa000
Apr 12 14:52:58 chaos kernel: esi: 12345678 edi: 00000286 ebp: dead0000 esp: c82d9f8c
Apr 12 14:52:58 chaos kernel: ds: 0018 es: 0018 ss: 0018
Apr 12 14:52:58 chaos kernel: Process tester (pid: 172, process nr: 30, stackpage=c82d9000)
Apr 12 14:52:58 chaos kernel: Stack: ffffffe7 c82d8000 c012ef20 c7e83a90 c91abde0 dead0000 12345678 c82d8000
Apr 12 14:52:58 chaos kernel: 00000002 00000004 bffff7a4 c7e83a90 c82d9fc4 c0107b74 00000004 dead0000
Apr 12 14:52:58 chaos kernel: 12345678 00000002 00000004 bffff7a4 00000036 0000002b 0000002b 00000036
Apr 12 14:52:58 chaos kernel: Call Trace: [sys_ioctl+416/464] [system_call+52/56]
Apr 12 14:52:58 chaos kernel: Code: 89 06 e9 bf 00 00 00 89 f6 85 f6 0f 84 b0 00 00 00 b8 00 e0

Snippet of code from a driver:

static int device_ioctl(struct inode *inp, struct file *fp, unsigned int cmd, unsigned long arg)
{
long flags;
int result;
spin_lock_irqsave(&device_lock, flags);
result = 0;

switch(cmd)
{
case READ_INTR_COUNT:
if(arg)
{
printk("Calling verify_area(VERIFY_WRITE, %p, %d)\n", (void *)arg, sizeof(int));
result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
printk("Result was %d\n", result);
if(result) break;
*((int *) arg) = info->intrs;
}
else
result = -EINVAL;
break;

Cheers,
Dick Johnson
***** FILE SYSTEM WAS MODIFIED *****
Penguin : Linux version 2.2.5 on an i686 machine (400.59 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.

-
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/