//------------------------------------------------------------------- // findvmlist.c // // This module demonstrates use of 'vmalloc()' and 'vfree()' // to allocate a temporeary memory buffer in kernel-space. // It also shows how the address of a kernel symbol that was // not exported can be extracted from the 'System.map' file. // // NOTE: This module was written and tested using the kernel // version 2.4.18-14smp, which exported the names of system- // call functions; it is left as an exercise for the student // to revise this module so it works with our 2.4.20 kernel. // // programmer: ALLAN CRUSE // written on: 04 MAR 2003 //------------------------------------------------------------------- #define __KERNEL__ #define MODULE #include // for init_module() #include // for create_proc_read_entry() #include // for vmalloc(), vfree() #include // for sys_open(), sys_read(), etc #include // for set_fs(), get_ds() #define SUCCESS 0 #define BASE_16 16 static char modname[] = "findvmlist"; static char mapfile[] = "/boot/System.map-2.4.18-14smp"; static struct vm_struct **vmlistp; static int my_proc_read( char *buf, char **start, off_t off, int count, int *eof, void *data ) { struct vm_struct *vm; int i = 0, len; len = sprintf( buf, "\nLinked-list of 'vm_struct' objects\n" ); vm = *vmlistp; while ( vm ) { ++i; len += sprintf( buf+len, "\n#%d:\t", i ); len += sprintf( buf+len, "addr=%08X ", vm->addr ); len += sprintf( buf+len, "size=%08X ", vm->size ); len += sprintf( buf+len, "flags=%08X ", vm->flags ); len += sprintf( buf+len, "next=%08X ", vm->next ); vm = vm->next; } len += sprintf( buf+len, "\n\n" ); *eof = 1; return len; } void cleanup_module( void ) { remove_proc_entry( modname, NULL ); printk( "<1>Removing \'%s\' module\n", modname ); } int init_module( void ) { int fd, filesize, nbytes; char *data, *cp; printk( "<1>\nInstalling \'%s\' module\n", modname ); set_fs( get_ds() ); // allow system-calls from this module // open the 'System.map' file fd = sys_open( mapfile, O_RDONLY, 0 ); if ( fd < 0 ) return -EINVAL; // determine the size of the file filesize = sys_lseek( fd, 0, 2 ); printk( "<1> filename: \'%s\' \n", mapfile ); printk( "<1> filesize: %d bytes \n", filesize ); // allocate enough memory for file contents data = (char *)vmalloc( filesize ); if ( !data ) return -ENOMEM; // rewind, then read the entire 'System.map' file sys_lseek( fd, 0, 0 ); nbytes = sys_read( fd, data, filesize ); if ( nbytes == filesize ) sys_close( fd ); else { vfree( data ); return -EFAULT; } // search line-by-line for the 'vmlist' symbol cp = strtok( data, "\n" ); while ( cp < data + filesize ) { if ( strstr( cp, "B vmlist" ) ) break; cp = strtok( NULL, "\n" ); if ( cp == NULL ) break; } if ( !cp ) { vfree( data ); return -ESRCH; } // extract the kernel address of the 'vmlist' variable vmlistp = (struct vm_struct**)simple_strtol( cp, NULL, BASE_16 ); vfree( data ); printk( "<1> address of \'vmlist\': %08X \n", vmlistp ); create_proc_read_entry( modname, 0, NULL, my_proc_read, NULL ); return SUCCESS; } MODULE_LICENSE("GPL");