@ -11,6 +11,7 @@
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/gfp.h>
# include <asm/system.h>
/*
@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
return copied < 0 ? - EFAULT : 0 ;
}
/*
* Copy memory in real mode ( kernel to kernel )
*/
int memcpy_real ( void * dest , void * src , size_t count )
{
register unsigned long _dest asm ( " 2 " ) = ( unsigned long ) dest ;
@ -101,3 +105,55 @@ void copy_to_absolute_zero(void *dest, void *src, size_t count)
__ctl_load ( cr0 , 0 , 0 ) ;
preempt_enable ( ) ;
}
/*
* Copy memory from kernel ( real ) to user ( virtual )
*/
int copy_to_user_real ( void __user * dest , void * src , size_t count )
{
int offs = 0 , size , rc ;
char * buf ;
buf = ( char * ) __get_free_page ( GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
rc = - EFAULT ;
while ( offs < count ) {
size = min ( PAGE_SIZE , count - offs ) ;
if ( memcpy_real ( buf , src + offs , size ) )
goto out ;
if ( copy_to_user ( dest + offs , buf , size ) )
goto out ;
offs + = size ;
}
rc = 0 ;
out :
free_page ( ( unsigned long ) buf ) ;
return rc ;
}
/*
* Copy memory from user ( virtual ) to kernel ( real )
*/
int copy_from_user_real ( void * dest , void __user * src , size_t count )
{
int offs = 0 , size , rc ;
char * buf ;
buf = ( char * ) __get_free_page ( GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
rc = - EFAULT ;
while ( offs < count ) {
size = min ( PAGE_SIZE , count - offs ) ;
if ( copy_from_user ( buf , src + offs , size ) )
goto out ;
if ( memcpy_real ( dest + offs , buf , size ) )
goto out ;
offs + = size ;
}
rc = 0 ;
out :
free_page ( ( unsigned long ) buf ) ;
return rc ;
}