2015-12-17 20:56:48 +03:00
/*
* Copyright ( c ) 2015 Dmitry V . Levin < ldv @ altlinux . org >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2015-11-15 05:22:44 +03:00
# include "defs.h"
# include <fcntl.h>
# include "xlat/uffd_flags.h"
SYS_FUNC ( userfaultfd )
{
printflags ( uffd_flags , tcp - > u_arg [ 0 ] , " UFFD_??? " ) ;
return RVAL_DECODED | RVAL_FD ;
}
2016-05-10 13:49:02 +03:00
# ifdef HAVE_LINUX_USERFAULTFD_H
# include <linux / ioctl.h>
# include <linux / userfaultfd.h>
# include "xlat / uffd_api_flags.h"
# include "xlat / uffd_copy_flags.h"
# include "xlat / uffd_register_ioctl_flags.h"
# include "xlat / uffd_register_mode_flags.h"
# include "xlat / uffd_zeropage_flags.h"
static void
tprintf_uffdio_range ( const struct uffdio_range * range )
{
tprintf ( " {start=%# " PRI__x64 " , len=%# " PRI__x64 " } " ,
range - > start , range - > len ) ;
}
int
uffdio_ioctl ( struct tcb * tcp , const unsigned int code , const long arg )
{
switch ( code ) {
case UFFDIO_API : {
struct uffdio_api ua ;
if ( entering ( tcp ) ) {
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & ua ) )
return RVAL_DECODED | 1 ;
/* Features is intended to contain some flags, but
* there aren ' t any defined yet .
*/
tprintf ( " {api=%# " PRI__x64
" , features=%# " PRI__x64 ,
ua . api , ua . features ) ;
} else {
if ( ! syserror ( tcp ) & & ! umove ( tcp , arg , & ua ) ) {
tprintf ( " , features.out=%# " PRI__x64
" , ioctls= " , ua . features ) ;
printflags64 ( uffd_api_flags , ua . ioctls ,
" _UFFDIO_??? " ) ;
}
2016-10-02 19:20:05 +03:00
tprints ( " } " ) ;
2016-05-10 13:49:02 +03:00
}
return 1 ;
}
case UFFDIO_COPY : {
struct uffdio_copy uc ;
if ( entering ( tcp ) ) {
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & uc ) )
return RVAL_DECODED | 1 ;
tprintf ( " {dst=%# " PRI__x64 " , src=%# " PRI__x64
" , len=%# " PRI__x64 " , mode= " ,
uc . dst , uc . src , uc . len ) ;
printflags64 ( uffd_copy_flags , uc . mode ,
" UFFDIO_COPY_??? " ) ;
} else {
if ( ! syserror ( tcp ) & & ! umove ( tcp , arg , & uc ) )
tprintf ( " , copy=%# " PRI__x64 , uc . copy ) ;
tprints ( " } " ) ;
}
return 1 ;
}
case UFFDIO_REGISTER : {
struct uffdio_register ur ;
if ( entering ( tcp ) ) {
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & ur ) )
return RVAL_DECODED | 1 ;
2016-10-02 19:20:05 +03:00
tprints ( " {range= " ) ;
2016-05-10 13:49:02 +03:00
tprintf_uffdio_range ( & ur . range ) ;
2016-10-02 19:20:05 +03:00
tprints ( " , mode= " ) ;
2016-05-10 13:49:02 +03:00
printflags64 ( uffd_register_mode_flags , ur . mode ,
" UFFDIO_REGISTER_MODE_??? " ) ;
} else {
if ( ! syserror ( tcp ) & & ! umove ( tcp , arg , & ur ) ) {
2016-10-02 19:20:05 +03:00
tprints ( " , ioctls= " ) ;
2016-05-10 13:49:02 +03:00
printflags64 ( uffd_register_ioctl_flags ,
ur . ioctls , " UFFDIO_??? " ) ;
}
tprints ( " } " ) ;
}
return 1 ;
}
case UFFDIO_UNREGISTER :
case UFFDIO_WAKE : {
struct uffdio_range ura ;
tprints ( " , " ) ;
if ( ! umove_or_printaddr ( tcp , arg , & ura ) )
tprintf_uffdio_range ( & ura ) ;
return RVAL_DECODED | 1 ;
}
case UFFDIO_ZEROPAGE : {
struct uffdio_zeropage uz ;
if ( entering ( tcp ) ) {
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & uz ) )
return RVAL_DECODED | 1 ;
2016-10-02 19:20:05 +03:00
tprints ( " {range= " ) ;
2016-05-10 13:49:02 +03:00
tprintf_uffdio_range ( & uz . range ) ;
2016-10-02 19:20:05 +03:00
tprints ( " , mode= " ) ;
2016-05-10 13:49:02 +03:00
printflags64 ( uffd_zeropage_flags , uz . mode ,
" UFFDIO_ZEROPAGE_??? " ) ;
} else {
if ( ! syserror ( tcp ) & & ! umove ( tcp , arg , & uz ) )
tprintf ( " , zeropage=%# " PRI__x64 , uz . zeropage ) ;
tprints ( " } " ) ;
}
return 1 ;
}
default :
return RVAL_DECODED ;
}
}
# endif /* HAVE_LINUX_USERFAULTFD_H */