2005-04-17 02:20:36 +04:00
/* uaccess.c: userspace access functions
*
* Copyright ( C ) 2004 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/mm.h>
2006-01-08 12:01:19 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
/*****************************************************************************/
/*
* copy a null terminated string from userspace
*/
2006-06-23 13:04:03 +04:00
long strncpy_from_user ( char * dst , const char __user * src , long count )
2005-04-17 02:20:36 +04:00
{
unsigned long max ;
char * p , ch ;
long err = - EFAULT ;
if ( count < 0 )
BUG ( ) ;
p = dst ;
# ifndef CONFIG_MMU
if ( ( unsigned long ) src < memory_start )
goto error ;
# endif
if ( ( unsigned long ) src > = get_addr_limit ( ) )
goto error ;
max = get_addr_limit ( ) - ( unsigned long ) src ;
if ( ( unsigned long ) count > max ) {
memset ( dst + max , 0 , count - max ) ;
count = max ;
}
err = 0 ;
for ( ; count > 0 ; count - - , p + + , src + + ) {
__get_user_asm ( err , ch , src , " ub " , " =r " ) ;
if ( err < 0 )
goto error ;
if ( ! ch )
break ;
* p = ch ;
}
err = p - dst ; /* return length excluding NUL */
error :
if ( count > 0 )
memset ( p , 0 , count ) ; /* clear remainder of buffer [security] */
return err ;
2006-01-08 12:01:19 +03:00
2005-04-17 02:20:36 +04:00
} /* end strncpy_from_user() */
2006-01-08 12:01:19 +03:00
EXPORT_SYMBOL ( strncpy_from_user ) ;
2005-04-17 02:20:36 +04:00
/*****************************************************************************/
/*
* Return the size of a string ( including the ending 0 )
*
* Return 0 on exception , a value greater than N if too long
*/
2006-06-23 13:04:03 +04:00
long strnlen_user ( const char __user * src , long count )
2005-04-17 02:20:36 +04:00
{
2006-06-23 13:04:03 +04:00
const char __user * p ;
2005-04-17 02:20:36 +04:00
long err = 0 ;
char ch ;
if ( count < 0 )
BUG ( ) ;
# ifndef CONFIG_MMU
if ( ( unsigned long ) src < memory_start )
return 0 ;
# endif
if ( ( unsigned long ) src > = get_addr_limit ( ) )
return 0 ;
for ( p = src ; count > 0 ; count - - , p + + ) {
__get_user_asm ( err , ch , p , " ub " , " =r " ) ;
if ( err < 0 )
return 0 ;
if ( ! ch )
break ;
}
return p - src + 1 ; /* return length including NUL */
2006-01-08 12:01:19 +03:00
2005-04-17 02:20:36 +04:00
} /* end strnlen_user() */
2006-01-08 12:01:19 +03:00
EXPORT_SYMBOL ( strnlen_user ) ;