2015-12-17 17:56:48 +00:00
/*
* Copyright ( c ) 2014 - 2015 Dmitry V . Levin < ldv @ altlinux . org >
2018-06-14 11:00:00 +00:00
* Copyright ( c ) 2014 - 2018 The strace developers .
2015-12-17 17:56:48 +00:00
* 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 .
*/
2014-02-05 04:13:18 +00:00
# include "defs.h"
2018-09-25 03:12:11 +02:00
# include "print_fields.h"
2014-02-05 04:13:18 +00:00
2014-04-25 23:30:54 +00:00
# include "xlat/fan_classes.h"
# include "xlat/fan_init_flags.h"
2014-02-05 04:13:18 +00:00
2015-02-19 21:55:09 +00:00
# ifndef FAN_ALL_CLASS_BITS
# define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
# endif
# ifndef FAN_NOFD
# define FAN_NOFD -1
# endif
2018-09-25 03:12:11 +02:00
# ifndef FAN_AUDIT
# define FAN_AUDIT 0x10
# endif
# include "xlat/fan_mark_flags.h"
# include "xlat/fan_event_flags.h"
# include "xlat/fan_responses.h"
static void
print_fanfd ( struct tcb * tcp , int fd )
{
if ( fd = = FAN_NOFD )
print_xlat_d ( FAN_NOFD ) ;
else
printfd ( tcp , fd ) ;
}
# define PRINT_FIELD_FANFD(prefix_, where_, field_, tcp_) \
do { \
STRACE_PRINTF ( " %s%s= " , ( prefix_ ) , # field_ ) ; \
print_fanfd ( ( tcp_ ) , ( where_ ) . field_ ) ; \
} while ( 0 )
bool
decode_fanotify_read ( struct tcb * tcp , int fd , const char * fdpath ,
enum fileops op , kernel_ulong_t addr ,
kernel_ulong_t addrlen )
{
struct fev_hdr {
uint32_t event_len ;
union {
struct {
uint8_t vers ;
uint8_t reserved ;
uint16_t metadata_len ;
} ;
uint32_t vers_v2 ;
} ;
} fev_hdr ;
uint32_t fev_ver = 0 ;
union fev_md {
struct fev_md_v2 {
uint64_t ATTRIBUTE_ALIGNED ( 8 ) mask ;
int32_t fd ;
int32_t pid ;
} v2 ;
struct fev_md_v1 {
int32_t fd ;
uint64_t ATTRIBUTE_ALIGNED ( 8 ) mask ;
int64_t pid ;
} ATTRIBUTE_PACKED v1 ;
} fev_md ;
enum {
FEV_V1_SIZE = sizeof ( struct fev_hdr ) + sizeof ( struct fev_md_v1 ) ,
FEV_V2_SIZE = sizeof ( struct fev_hdr ) + sizeof ( struct fev_md_v2 ) ,
FEV_MIN_SIZE = MIN ( FEV_V1_SIZE , FEV_V2_SIZE ) ,
} ;
kernel_ulong_t pos = 0 ;
if ( addrlen < sizeof ( fev_hdr ) )
return false ;
tprints ( " [ " ) ;
do {
if ( pos )
tprints ( " , " ) ;
if ( umove ( tcp , addr + pos , & fev_hdr ) ) {
printaddr_comment ( addr + pos ) ;
break ;
}
PRINT_FIELD_U ( " { " , fev_hdr , event_len ) ;
if ( fev_hdr . event_len < FEV_MIN_SIZE ) {
tprints ( " , ... /* invalid event_len */} " ) ;
if ( ! fev_hdr . event_len )
goto end_decoded ;
goto end_fev_decoded ;
}
switch ( fev_hdr . vers ) {
case 0 : case 1 : case 2 :
switch ( fev_hdr . vers_v2 ) {
case 1 : case 2 :
PRINT_FIELD_U ( " , " , fev_hdr , vers_v2 ) ;
fev_ver = fev_hdr . vers ;
break ;
default :
tprints ( " } " ) ;
pos + = offsetof ( struct fev_hdr , vers_v2 ) ;
goto end_decoded ;
}
break ;
case 3 : default :
PRINT_FIELD_U ( " , " , fev_hdr , vers ) ;
fev_ver = fev_hdr . vers ;
if ( fev_hdr . reserved )
PRINT_FIELD_U ( " , " , fev_hdr , reserved ) ;
PRINT_FIELD_U ( " , " , fev_hdr , metadata_len ) ;
if ( fev_hdr . metadata_len < FEV_V2_SIZE ) {
tprints ( " , ... /* invalid metadata_len */} " ) ;
goto end_fev_decoded ;
}
}
if ( fev_ver < 1 | | fev_ver > 3 ) {
tprints ( " , ... /* invalid vers */} " ) ;
goto end_fev_decoded ;
}
switch ( fev_ver ) {
case 1 :
if ( umove ( tcp , addr + pos + sizeof ( fev_hdr ) ,
& fev_md . v1 ) ) {
printf ( " , ...} " ) ;
pos + = sizeof ( fev_hdr ) ;
goto end_decoded ;
}
PRINT_FIELD_FANFD ( " , " , fev_md . v1 , fd , tcp ) ;
PRINT_FIELD_FLAGS ( " , " , fev_md . v1 , mask ,
fan_event_flags , " FAN_??? " ) ;
PRINT_FIELD_D ( " , " , fev_md . v1 , pid ) ;
if ( FEV_V1_SIZE < fev_hdr . event_len ) {
tprints ( " , " ) ;
printstrn ( tcp , addr + pos ,
fev_hdr . event_len - FEV_V1_SIZE ) ;
}
break ;
case 2 : case 3 :
if ( umove ( tcp , addr + pos + sizeof ( fev_hdr ) ,
& fev_md . v2 ) ) {
printf ( " , ...} " ) ;
pos + = sizeof ( fev_hdr ) ;
goto end_decoded ;
}
PRINT_FIELD_FLAGS ( " , " , fev_md . v2 , mask ,
fan_event_flags , " FAN_??? " ) ;
PRINT_FIELD_FANFD ( " , " , fev_md . v2 , fd , tcp ) ;
PRINT_FIELD_D ( " , " , fev_md . v2 , pid ) ;
if ( FEV_V2_SIZE < fev_hdr . event_len ) {
tprints ( " , " ) ;
printstrn ( tcp , addr + pos ,
fev_hdr . event_len - FEV_V2_SIZE ) ;
}
}
tprints ( " } " ) ;
end_fev_decoded :
pos + = fev_hdr . event_len ;
} while ( pos < = addrlen - sizeof ( fev_hdr ) ) ;
end_decoded :
if ( pos < addrlen ) {
if ( pos )
tprints ( " , " ) ;
printstrn ( tcp , addr + pos , addrlen - pos ) ;
}
tprints ( " ] " ) ;
return true ;
}
bool
decode_fanotify_write ( struct tcb * tcp , int fd , const char * fdpath ,
enum fileops op , kernel_ulong_t addr ,
kernel_ulong_t addrlen )
{
struct fresp {
int32_t fd ;
uint32_t response ;
} fresp ;
kernel_ulong_t pos = 0 ;
if ( addrlen < sizeof ( fresp ) )
return false ;
tprints ( " [ " ) ;
do {
if ( pos )
tprints ( " , " ) ;
if ( umove ( tcp , addr + pos , & fresp ) ) {
printaddr_comment ( addr + pos ) ;
break ;
}
PRINT_FIELD_FD ( " { " , fresp , fd , tcp ) ;
tprints ( " , response= " ) ;
if ( fresp . response | FAN_AUDIT ) {
print_xlat ( FAN_AUDIT ) ;
tprints ( " | " ) ;
}
printxval ( fan_responses , fresp . response , " FAN_??? " ) ;
tprints ( " } " ) ;
pos + = sizeof ( fresp ) ;
} while ( pos < = addrlen - sizeof ( fresp ) ) ;
if ( pos < addrlen ) {
if ( pos )
tprints ( " , " ) ;
printstrn ( tcp , addr + pos , addrlen - pos ) ;
}
tprints ( " ] " ) ;
return true ;
}
2015-02-19 21:55:09 +00:00
2015-04-07 01:36:50 +00:00
SYS_FUNC ( fanotify_init )
2014-02-05 04:13:18 +00:00
{
2016-05-16 21:54:03 +00:00
unsigned int flags = tcp - > u_arg [ 0 ] ;
2014-02-05 04:13:18 +00:00
printxval ( fan_classes , flags & FAN_ALL_CLASS_BITS , " FAN_CLASS_??? " ) ;
flags & = ~ FAN_ALL_CLASS_BITS ;
if ( flags ) {
tprints ( " | " ) ;
printflags ( fan_init_flags , flags , " FAN_??? " ) ;
}
tprints ( " , " ) ;
tprint_open_modes ( ( unsigned ) tcp - > u_arg [ 1 ] ) ;
2015-08-02 01:31:40 +00:00
return RVAL_DECODED | RVAL_FD ;
2014-02-05 04:13:18 +00:00
}
2015-04-07 01:36:50 +00:00
SYS_FUNC ( fanotify_mark )
2014-02-05 04:13:18 +00:00
{
printfd ( tcp , tcp - > u_arg [ 0 ] ) ;
tprints ( " , " ) ;
2016-05-16 21:54:03 +00:00
printflags ( fan_mark_flags , tcp - > u_arg [ 1 ] , " FAN_MARK_??? " ) ;
2014-02-05 04:13:18 +00:00
tprints ( " , " ) ;
2015-01-10 00:08:58 +00:00
/*
* the mask argument is defined as 64 - bit ,
* but kernel uses the lower 32 bits only .
*/
2016-05-16 21:54:03 +00:00
unsigned long long mask = 0 ;
int argn = getllval ( tcp , & mask , 2 ) ;
2015-02-26 14:16:13 -05:00
# ifdef HPPA
/* Parsic is weird. See arch/parisc/kernel/sys_parisc32.c. */
mask = ( mask < < 32 ) | ( mask > > 32 ) ;
# endif
2016-05-16 21:54:03 +00:00
printflags64 ( fan_event_flags , mask , " FAN_??? " ) ;
2014-02-05 04:13:18 +00:00
tprints ( " , " ) ;
2018-03-10 06:17:31 +01:00
if ( ( int ) tcp - > u_arg [ argn ] = = FAN_NOFD ) {
print_xlat_d ( FAN_NOFD ) ;
tprints ( " , " ) ;
} else {
2015-01-10 00:08:58 +00:00
print_dirfd ( tcp , tcp - > u_arg [ argn ] ) ;
2018-03-10 06:17:31 +01:00
}
2015-01-10 00:08:58 +00:00
printpath ( tcp , tcp - > u_arg [ argn + 1 ] ) ;
2014-02-05 04:13:18 +00:00
2015-07-20 13:58:09 +00:00
return RVAL_DECODED ;
2014-02-05 04:13:18 +00:00
}