2005-04-16 15:20:36 -07: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 01:01:19 -08:00
# include <linux/module.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
/*****************************************************************************/
/*
* copy a null terminated string from userspace
*/
2006-06-23 02:04:03 -07:00
long strncpy_from_user ( char * dst , const char __user * src , long count )
2005-04-16 15:20:36 -07:00
{
unsigned long max ;
char * p , ch ;
long err = - EFAULT ;
2009-06-11 13:05:04 +01:00
BUG_ON ( count < 0 ) ;
2005-04-16 15:20:36 -07:00
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 01:01:19 -08:00
2005-04-16 15:20:36 -07:00
} /* end strncpy_from_user() */
2006-01-08 01:01:19 -08:00
EXPORT_SYMBOL ( strncpy_from_user ) ;
2005-04-16 15:20:36 -07: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 02:04:03 -07:00
long strnlen_user ( const char __user * src , long count )
2005-04-16 15:20:36 -07:00
{
2006-06-23 02:04:03 -07:00
const char __user * p ;
2005-04-16 15:20:36 -07:00
long err = 0 ;
char ch ;
2009-06-11 13:05:04 +01:00
BUG_ON ( count < 0 ) ;
2005-04-16 15:20:36 -07:00
# 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 01:01:19 -08:00
2005-04-16 15:20:36 -07:00
} /* end strnlen_user() */
2006-01-08 01:01:19 -08:00
EXPORT_SYMBOL ( strnlen_user ) ;