2005-05-04 15:20:54

by Leszek Koltunski

[permalink] [raw]
Subject: Cannot read from /dev/kmem


Kernel 2.6.11 , I cannot seem to be able to read from /dev/kmem... The
following little proggie

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

struct {
unsigned short limit;
unsigned int base;
} __attribute__ ((packed)) idtr;

struct {
unsigned short off1;
unsigned short sel;
unsigned char none,flags;
unsigned short off2;
} __attribute__ ((packed)) idt;

int main()
{
int result, kmem = open ("/dev/kmem",O_RDONLY);

asm ("sidt %0" : "=m" (idtr));
printf("idtr base at 0x%X\n",(int)idtr.base);

if (kmem<0) return 1;

if (lseek(kmem, idtr.base + 8*0x80,SEEK_SET) != idtr.base +
8*0x80 )
{
perror("kmem lseek"); exit(1);
}

result = read(kmem, &idt , sizeof(idt) );

if( result != sizeof(idt) )
{
printf("result: %d, sizeof(idt)= %d errno=%d\n", result,
sizeof(idt), errno);
}

close(kmem);

return 0;
}



returns

utumno:/home/leszek/progs/module/hijack# ./test
idtr base at 0xC0423000
result: -1, sizeof(idt)= 8 errno=22


??? EINVAL

I remember this working on a 2.4.x kernel....

Leszek Koltunski


2005-05-05 00:44:11

by Arjan van de Ven

[permalink] [raw]
Subject: Re: Cannot read from /dev/kmem

On Wed, 2005-05-04 at 17:20 +0200, Leszek Koltunski wrote:
> utumno:/home/leszek/progs/module/hijack# ./test

if you want to write exploits and rootkits you're better off mailing
[email protected] and not this list.



2005-05-04 22:43:01

by Randy.Dunlap

[permalink] [raw]
Subject: Re: Cannot read from /dev/kmem

On Wed, 4 May 2005 17:20:36 +0200 (CEST)
Leszek Koltunski <[email protected]> wrote:

>
> Kernel 2.6.11 , I cannot seem to be able to read from /dev/kmem... The
> following little proggie
>
> #include <stdio.h>
> #include <fcntl.h>
> #include <errno.h>
>
> struct {
> unsigned short limit;
> unsigned int base;
> } __attribute__ ((packed)) idtr;
>
> struct {
> unsigned short off1;
> unsigned short sel;
> unsigned char none,flags;
> unsigned short off2;
> } __attribute__ ((packed)) idt;
>
> int main()
> {
> int result, kmem = open ("/dev/kmem",O_RDONLY);
>
> asm ("sidt %0" : "=m" (idtr));
> printf("idtr base at 0x%X\n",(int)idtr.base);
>
> if (kmem<0) return 1;
>
> if (lseek(kmem, idtr.base + 8*0x80,SEEK_SET) != idtr.base +
> 8*0x80 )
> {
> perror("kmem lseek"); exit(1);
> }
>
> result = read(kmem, &idt , sizeof(idt) );
>
> if( result != sizeof(idt) )
> {
> printf("result: %d, sizeof(idt)= %d errno=%d\n", result,
> sizeof(idt), errno);
> }
>
> close(kmem);
>
> return 0;
> }
>
> returns
>
> utumno:/home/leszek/progs/module/hijack# ./test
> idtr base at 0xC0423000
> result: -1, sizeof(idt)= 8 errno=22
>
> ??? EINVAL
>
> I remember this working on a 2.4.x kernel....

Hm, let me see if I can explain what I see here...

vfs_llseek() sets f_pos (file position) to 0xffffffff.c04230000 (due
to sign extension). In read(), rw_verify_area() sees that pos
as < 0 and balks on it.

I futzed around with lseek() and read(), to no avail.
However, I did get your test program to work by using lseek64()
instead of lseek(). It prints (after I added code) a selector
value of 0x60, which makes sense.

Maybe you have to use llseek() or lseek64() with large 32-bit
file offsets (that look like 32-bit negative numbers)...
I dunno.

HTH.
---
~Randy