2016-12-26 15:24:45 +03:00
/*
* Support for decoding of DM_ * ioctl commands .
*
* Copyright ( c ) 2016 Mikulas Patocka < mpatocka @ redhat . com >
* Copyright ( c ) 2016 Masatake Yamato < yamato @ redhat . com >
* Copyright ( c ) 2016 Dmitry V . Levin < ldv @ altlinux . org >
* Copyright ( c ) 2016 Eugene Syromyatnikov < evgsyr @ gmail . com >
2017-05-22 20:14:52 +03:00
* Copyright ( c ) 2016 - 2017 The strace developers .
2016-12-26 15:24:45 +03: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 .
*/
2016-10-03 00:59:06 +03:00
# include "defs.h"
# ifdef HAVE_LINUX_DM_IOCTL_H
2017-07-11 03:20:54 +03:00
# include "print_fields.h"
2016-10-03 00:59:06 +03:00
# include <linux / dm-ioctl.h>
# include <linux / ioctl.h>
# if DM_VERSION_MAJOR == 4
/* Definitions for command which have been added later */
# ifndef DM_LIST_VERSIONS
2017-09-17 04:51:51 +03:00
# define DM_LIST_VERSIONS _IOWR(DM_IOCTL, 0x0d, struct dm_ioctl)
2016-10-03 00:59:06 +03:00
# endif
# ifndef DM_TARGET_MSG
2017-09-17 04:51:51 +03:00
# define DM_TARGET_MSG _IOWR(DM_IOCTL, 0x0e, struct dm_ioctl)
2016-10-03 00:59:06 +03:00
# endif
# ifndef DM_DEV_SET_GEOMETRY
2017-09-17 04:51:51 +03:00
# define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, 0x0f, struct dm_ioctl)
# endif
# ifndef DM_DEV_ARM_POLL
# define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, 0x10, struct dm_ioctl)
2016-10-03 00:59:06 +03:00
# endif
static void
dm_decode_device ( const unsigned int code , const struct dm_ioctl * ioc )
{
switch ( code ) {
case DM_REMOVE_ALL :
case DM_LIST_DEVICES :
case DM_LIST_VERSIONS :
break ;
default :
2017-07-11 03:20:54 +03:00
if ( ioc - > dev )
2017-07-09 16:54:01 +03:00
PRINT_FIELD_DEV ( " , " , * ioc , dev ) ;
2017-07-11 03:20:54 +03:00
if ( ioc - > name [ 0 ] )
PRINT_FIELD_CSTRING ( " , " , * ioc , name ) ;
if ( ioc - > uuid [ 0 ] )
PRINT_FIELD_CSTRING ( " , " , * ioc , uuid ) ;
2016-10-03 00:59:06 +03:00
break ;
}
}
static void
dm_decode_values ( struct tcb * tcp , const unsigned int code ,
const struct dm_ioctl * ioc )
{
if ( entering ( tcp ) ) {
switch ( code ) {
case DM_TABLE_LOAD :
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " , " , * ioc , target_count ) ;
2016-10-03 00:59:06 +03:00
break ;
case DM_DEV_SUSPEND :
if ( ioc - > flags & DM_SUSPEND_FLAG )
break ;
/* Fall through */
case DM_DEV_RENAME :
case DM_DEV_REMOVE :
case DM_DEV_WAIT :
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " , " , * ioc , event_nr ) ;
2016-10-03 00:59:06 +03:00
break ;
}
} else if ( ! syserror ( tcp ) ) {
switch ( code ) {
case DM_DEV_CREATE :
case DM_DEV_RENAME :
case DM_DEV_SUSPEND :
case DM_DEV_STATUS :
case DM_DEV_WAIT :
case DM_TABLE_LOAD :
case DM_TABLE_CLEAR :
case DM_TABLE_DEPS :
case DM_TABLE_STATUS :
case DM_TARGET_MSG :
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " , " , * ioc , target_count ) ;
PRINT_FIELD_U ( " , " , * ioc , open_count ) ;
PRINT_FIELD_U ( " , " , * ioc , event_nr ) ;
2016-10-03 00:59:06 +03:00
break ;
}
}
}
# include "xlat/dm_flags.h"
static void
dm_decode_flags ( const struct dm_ioctl * ioc )
{
2017-07-14 03:08:09 +03:00
PRINT_FIELD_FLAGS ( " , " , * ioc , flags , dm_flags , " DM_??? " ) ;
2016-10-03 00:59:06 +03:00
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_dm_target_spec ( struct tcb * const tcp , const kernel_ulong_t addr ,
2016-12-21 06:03:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
static const uint32_t target_spec_size =
sizeof ( struct dm_target_spec ) ;
uint32_t i ;
uint32_t offset = ioc - > data_start ;
2017-04-24 22:14:41 +03:00
uint32_t offset_end = 0 ;
2016-10-03 00:59:06 +03:00
if ( abbrev ( tcp ) ) {
if ( ioc - > target_count )
tprints ( " , ... " ) ;
return ;
}
for ( i = 0 ; i < ioc - > target_count ; i + + ) {
2017-04-24 22:14:41 +03:00
tprints ( " , " ) ;
if ( i & & offset < = offset_end )
goto misplaced ;
2016-10-03 00:59:06 +03:00
offset_end = offset + target_spec_size ;
if ( offset_end < = offset | | offset_end > ioc - > data_size )
goto misplaced ;
if ( i > = max_strlen ) {
tprints ( " ... " ) ;
break ;
}
2017-04-24 22:14:41 +03:00
struct dm_target_spec s ;
2016-10-03 00:59:06 +03:00
if ( umove_or_printaddr ( tcp , addr + offset , & s ) )
break ;
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " { " , s , sector_start ) ;
PRINT_FIELD_U ( " , " , s , length ) ;
2016-10-03 00:59:06 +03:00
if ( exiting ( tcp ) )
2017-07-14 03:08:09 +03:00
PRINT_FIELD_D ( " , " , s , status ) ;
2016-10-03 00:59:06 +03:00
2017-07-11 03:20:54 +03:00
PRINT_FIELD_CSTRING ( " , " , s , target_type ) ;
2016-10-03 00:59:06 +03:00
tprints ( " , string= " ) ;
printstr_ex ( tcp , addr + offset_end , ioc - > data_size - offset_end ,
QUOTE_0_TERMINATED ) ;
2017-02-18 03:58:17 +03:00
tprints ( " } " ) ;
2016-10-03 00:59:06 +03:00
if ( entering ( tcp ) )
offset + = s . next ;
else
offset = ioc - > data_start + s . next ;
}
return ;
misplaced :
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced struct dm_target_spec " ) ;
2016-10-03 00:59:06 +03:00
}
bool
dm_print_dev ( struct tcb * tcp , void * dev_ptr , size_t dev_size , void * dummy )
{
uint64_t * dev = ( uint64_t * ) dev_ptr ;
2016-12-26 15:25:35 +03:00
print_dev_t ( * dev ) ;
2016-10-03 00:59:06 +03:00
return 1 ;
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_dm_target_deps ( struct tcb * const tcp , const kernel_ulong_t addr ,
2016-12-21 06:03:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
2017-04-24 22:14:41 +03:00
if ( ioc - > data_start = = ioc - > data_size )
return ;
tprints ( " , " ) ;
if ( abbrev ( tcp ) ) {
tprints ( " ... " ) ;
return ;
}
2016-10-03 00:59:06 +03:00
static const uint32_t target_deps_dev_offs =
offsetof ( struct dm_target_deps , dev ) ;
uint64_t dev_buf ;
struct dm_target_deps s ;
uint32_t offset = ioc - > data_start ;
uint32_t offset_end = offset + target_deps_dev_offs ;
uint32_t space ;
if ( offset_end < = offset | | offset_end > ioc - > data_size )
goto misplaced ;
if ( umove_or_printaddr ( tcp , addr + offset , & s ) )
return ;
space = ( ioc - > data_size - offset_end ) / sizeof ( dev_buf ) ;
if ( s . count > space )
goto misplaced ;
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " { " , s , count ) ;
2016-10-03 00:59:06 +03:00
2017-07-14 03:08:09 +03:00
tprints ( " , deps= " ) ;
2016-10-03 00:59:06 +03:00
print_array ( tcp , addr + offset_end , s . count , & dev_buf , sizeof ( dev_buf ) ,
umoven_or_printaddr , dm_print_dev , NULL ) ;
tprints ( " } " ) ;
return ;
misplaced :
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced struct dm_target_deps " ) ;
2016-10-03 00:59:06 +03:00
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_dm_name_list ( struct tcb * const tcp , const kernel_ulong_t addr ,
2016-12-21 06:03:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
static const uint32_t name_list_name_offs =
offsetof ( struct dm_name_list , name ) ;
struct dm_name_list s ;
uint32_t offset = ioc - > data_start ;
2017-04-24 22:14:41 +03:00
uint32_t offset_end = 0 ;
2016-10-03 00:59:06 +03:00
uint32_t count ;
dm: add support for event_nr in DM_LIST_DEVICES result
Commit v4.13-rc1~137^2~13 (and a follow-up fix v4.14-rc4~20^2~3
that changed alignment) introduced an additional hidden field
in the structure returned by DM_LIST_DEVICES ioctl command
that contains event_nr information.
Unfortunately, we can't test it for now, but looks like it kinda works:
# ./strace -v -eioctl -y dmsetup ls
ioctl(3</dev/mapper/control>, DM_VERSION, {version=4.0.0,
data_size=16384, flags=DM_EXISTS_FLAG} => {version=4.37.0,
data_size=16384, flags=DM_EXISTS_FLAG}) = 0
ioctl(3</dev/mapper/control>, DM_LIST_DEVICES, {version=4.0.0,
data_size=16384, data_start=312, flags=DM_EXISTS_FLAG} =>
{version=4.37.0, data_size=408, data_start=312, flags=DM_EXISTS_FLAG,
{dev=makedev(253, 1), name="fedoratesting--30-swap", event_nr=0},
{dev=makedev(253, 0), name="fedoratesting--30-root"}}) = 0
fedoratesting--30-swap (253:1)
fedoratesting--30-root (253:0)
* dm.c (dm_decode_dm_name_list): Obtain the amount of bytes copied
during printing device name, print event number if there's a suitable
gap present and the DM version is high enough.
* NEWS: Mention it.
2017-09-17 05:58:49 +03:00
int rc ;
2016-10-03 00:59:06 +03:00
2017-04-24 22:14:41 +03:00
if ( ioc - > data_start = = ioc - > data_size )
return ;
2016-10-03 00:59:06 +03:00
if ( abbrev ( tcp ) ) {
tprints ( " , ... " ) ;
return ;
}
for ( count = 0 ; ; count + + ) {
2017-04-24 22:14:41 +03:00
tprints ( " , " ) ;
if ( count & & offset < = offset_end )
goto misplaced ;
2016-10-03 00:59:06 +03:00
offset_end = offset + name_list_name_offs ;
if ( offset_end < = offset | | offset_end > ioc - > data_size )
goto misplaced ;
if ( count > = max_strlen ) {
tprints ( " ... " ) ;
break ;
}
if ( umove_or_printaddr ( tcp , addr + offset , & s ) )
break ;
2017-07-09 16:54:01 +03:00
PRINT_FIELD_DEV ( " { " , s , dev ) ;
tprints ( " , name= " ) ;
dm: add support for event_nr in DM_LIST_DEVICES result
Commit v4.13-rc1~137^2~13 (and a follow-up fix v4.14-rc4~20^2~3
that changed alignment) introduced an additional hidden field
in the structure returned by DM_LIST_DEVICES ioctl command
that contains event_nr information.
Unfortunately, we can't test it for now, but looks like it kinda works:
# ./strace -v -eioctl -y dmsetup ls
ioctl(3</dev/mapper/control>, DM_VERSION, {version=4.0.0,
data_size=16384, flags=DM_EXISTS_FLAG} => {version=4.37.0,
data_size=16384, flags=DM_EXISTS_FLAG}) = 0
ioctl(3</dev/mapper/control>, DM_LIST_DEVICES, {version=4.0.0,
data_size=16384, data_start=312, flags=DM_EXISTS_FLAG} =>
{version=4.37.0, data_size=408, data_start=312, flags=DM_EXISTS_FLAG,
{dev=makedev(253, 1), name="fedoratesting--30-swap", event_nr=0},
{dev=makedev(253, 0), name="fedoratesting--30-root"}}) = 0
fedoratesting--30-swap (253:1)
fedoratesting--30-root (253:0)
* dm.c (dm_decode_dm_name_list): Obtain the amount of bytes copied
during printing device name, print event number if there's a suitable
gap present and the DM version is high enough.
* NEWS: Mention it.
2017-09-17 05:58:49 +03:00
rc = printstr_ex ( tcp , addr + offset_end ,
ioc - > data_size - offset_end ,
QUOTE_0_TERMINATED ) ;
/*
* In Linux v4 .13 - rc1 ~ 137 ^ 2 ~ 13 it has been decided to cram in
* one more undocumented field after the device name , as if the
* format decoding was not twisted enough already . So , we have
* to check " next " now , and if it _looks like_ that there is
* a space for one additional integer , let ' s print it . As if the
* perversity with " name string going further than pointer to
* the next one " wasn't enough. Moreover, the calculation was
* broken for m32 on 64 - bit kernels until v4 .14 - rc4 ~ 20 ^ 2 ~ 3 , and
* we have no ability to detect kernel bit - ness ( on x86 , at
* least ) , so refrain from printing it for the DM versions below
* 4.37 ( the original version was also aligned differently than
* now even on 64 bit ) .
*/
if ( ( rc > 0 ) & & ioc - > version [ 1 ] > = 37 ) {
kernel_ulong_t event_addr =
( addr + offset_end + rc + 7 ) & ~ 7 ;
uint32_t event_nr ;
if ( ( event_addr + sizeof ( event_nr ) ) < =
( addr + offset + s . next ) & &
! umove ( tcp , event_addr , & event_nr ) )
tprintf ( " , event_nr=% " PRIu32 , event_nr ) ;
}
2016-10-03 00:59:06 +03:00
tprints ( " } " ) ;
if ( ! s . next )
break ;
offset + = s . next ;
}
return ;
misplaced :
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced struct dm_name_list " ) ;
2016-10-03 00:59:06 +03:00
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_dm_target_versions ( struct tcb * const tcp , const kernel_ulong_t addr ,
2016-12-21 06:03:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
static const uint32_t target_vers_name_offs =
offsetof ( struct dm_target_versions , name ) ;
struct dm_target_versions s ;
uint32_t offset = ioc - > data_start ;
2017-04-24 22:14:41 +03:00
uint32_t offset_end = 0 ;
2016-10-03 00:59:06 +03:00
uint32_t count ;
2017-04-24 22:14:41 +03:00
if ( ioc - > data_start = = ioc - > data_size )
return ;
2016-10-03 00:59:06 +03:00
if ( abbrev ( tcp ) ) {
tprints ( " , ... " ) ;
return ;
}
for ( count = 0 ; ; count + + ) {
2017-04-24 22:14:41 +03:00
tprints ( " , " ) ;
if ( count & & offset < = offset_end )
goto misplaced ;
2016-10-03 00:59:06 +03:00
offset_end = offset + target_vers_name_offs ;
if ( offset_end < = offset | | offset_end > ioc - > data_size )
goto misplaced ;
if ( count > = max_strlen ) {
tprints ( " ... " ) ;
break ;
}
if ( umove_or_printaddr ( tcp , addr + offset , & s ) )
break ;
tprints ( " {name= " ) ;
printstr_ex ( tcp , addr + offset_end , ioc - > data_size - offset_end ,
QUOTE_0_TERMINATED ) ;
tprintf ( " , version=% " PRIu32 " .% " PRIu32 " .% " PRIu32 " } " ,
s . version [ 0 ] , s . version [ 1 ] , s . version [ 2 ] ) ;
if ( ! s . next )
break ;
offset + = s . next ;
}
return ;
misplaced :
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced struct dm_target_versions " ) ;
2016-10-03 00:59:06 +03:00
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_dm_target_msg ( struct tcb * const tcp , const kernel_ulong_t addr ,
2017-06-18 01:23:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
2017-04-24 22:14:41 +03:00
if ( ioc - > data_start = = ioc - > data_size )
return ;
tprints ( " , " ) ;
2016-10-03 00:59:06 +03:00
if ( abbrev ( tcp ) ) {
2017-04-24 22:14:41 +03:00
tprints ( " ... " ) ;
2016-10-03 00:59:06 +03:00
return ;
}
2017-04-24 22:14:41 +03:00
static const uint32_t target_msg_message_offs =
offsetof ( struct dm_target_msg , message ) ;
uint32_t offset = ioc - > data_start ;
uint32_t offset_end = offset + target_msg_message_offs ;
2016-10-03 00:59:06 +03:00
if ( offset_end > offset & & offset_end < = ioc - > data_size ) {
struct dm_target_msg s ;
if ( umove_or_printaddr ( tcp , addr + offset , & s ) )
return ;
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " { " , s , sector ) ;
tprints ( " , message= " ) ;
2016-10-03 00:59:06 +03:00
printstr_ex ( tcp , addr + offset_end , ioc - > data_size - offset_end ,
QUOTE_0_TERMINATED ) ;
tprints ( " } " ) ;
} else {
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced struct dm_target_msg " ) ;
2016-10-03 00:59:06 +03:00
}
}
static void
2016-12-26 13:26:03 +03:00
dm_decode_string ( struct tcb * const tcp , const kernel_ulong_t addr ,
2016-12-21 06:03:09 +03:00
const struct dm_ioctl * const ioc )
2016-10-03 00:59:06 +03:00
{
2017-04-24 22:14:41 +03:00
tprints ( " , " ) ;
2016-10-03 00:59:06 +03:00
if ( abbrev ( tcp ) ) {
2017-04-24 22:14:41 +03:00
tprints ( " ... " ) ;
2016-10-03 00:59:06 +03:00
return ;
}
2017-04-24 22:14:41 +03:00
uint32_t offset = ioc - > data_start ;
if ( offset < = ioc - > data_size ) {
tprints ( " string= " ) ;
2016-10-03 00:59:06 +03:00
printstr_ex ( tcp , addr + offset , ioc - > data_size - offset ,
QUOTE_0_TERMINATED ) ;
} else {
2017-04-24 22:14:41 +03:00
tprints ( " ??? " ) ;
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " misplaced string " ) ;
2016-10-03 00:59:06 +03:00
}
}
static inline bool
dm_ioctl_has_params ( const unsigned int code )
{
switch ( code ) {
case DM_VERSION :
case DM_REMOVE_ALL :
case DM_DEV_CREATE :
case DM_DEV_REMOVE :
case DM_DEV_SUSPEND :
case DM_DEV_STATUS :
case DM_TABLE_CLEAR :
2017-09-17 04:51:51 +03:00
case DM_DEV_ARM_POLL :
2016-10-03 00:59:06 +03:00
return false ;
}
return true ;
}
static int
Change type of ioctl 3rd argument from long to kernel_ureg_t
* defs.h (DECL_IOCTL): Change arg type from long to kernel_ureg_t.
* dm.c (dm_known_ioctl, dm_ioctl): Likewise.
* file_ioctl.c (file_ioctl): Likewise.
* fs_x_ioctl.c (fs_x_ioctl): Likewise.
* ioctl.c (ioctl_decode): Likewise.
* loop.c (decode_loop_info, decode_loop_info64): Change addr type
from long to kernel_ureg_t.
(loop_ioctl): Change arg type from long to kernel_ureg_t.
* ptp.c (ptp_ioctl): Likewise.
* scsi.c (print_sg_io_v3_req, print_sg_io_v3_res, print_sg_io_v4_req,
print_sg_io_v4_res, scsi_ioctl): Likewise.
* sock.c (print_ifreq, sock_ioctl): Likewise.
(decode_ifconf): Change addr type from long to kernel_ureg_t.
* term.c (decode_termios, decode_termio, decode_winsize, decode_ttysize,
decode_modem_flags): Likewise.
(term_ioctl): Change arg type from long to kernel_ureg_t.
* ubi.c (ubi_ioctl): Likewise.
* userfaultfd.c (uffdio_ioctl): Likewise.
2016-12-21 06:03:09 +03:00
dm_known_ioctl ( struct tcb * const tcp , const unsigned int code ,
2016-12-26 13:26:03 +03:00
const kernel_ulong_t arg )
2016-10-03 00:59:06 +03:00
{
struct dm_ioctl * ioc = NULL ;
struct dm_ioctl * entering_ioc = NULL ;
bool ioc_changed = false ;
if ( entering ( tcp ) ) {
ioc = malloc ( sizeof ( * ioc ) ) ;
if ( ! ioc )
return 0 ;
} else {
ioc = alloca ( sizeof ( * ioc ) ) ;
}
if ( ( umoven ( tcp , arg , offsetof ( struct dm_ioctl , data ) , ioc ) < 0 ) | |
( ioc - > data_size < offsetof ( struct dm_ioctl , data_size ) ) ) {
if ( entering ( tcp ) )
free ( ioc ) ;
return 0 ;
}
if ( entering ( tcp ) )
set_tcb_priv_data ( tcp , ioc , free ) ;
else {
entering_ioc = get_tcb_priv_data ( tcp ) ;
/*
* retrieve_status , __dev_status called only in case of success ,
* so it looks like there ' s no need to check open_count ,
* event_nr , target_count , dev fields for change ( they are
* printed only in case of absence of errors ) .
*/
if ( ! entering_ioc | |
( ioc - > version [ 0 ] ! = entering_ioc - > version [ 0 ] ) | |
( ioc - > version [ 1 ] ! = entering_ioc - > version [ 1 ] ) | |
( ioc - > version [ 2 ] ! = entering_ioc - > version [ 2 ] ) | |
( ioc - > data_size ! = entering_ioc - > data_size ) | |
( ioc - > data_start ! = entering_ioc - > data_start ) | |
( ioc - > flags ! = entering_ioc - > flags ) )
ioc_changed = true ;
}
if ( exiting ( tcp ) & & syserror ( tcp ) & & ! ioc_changed )
2017-08-28 03:39:15 +03:00
return RVAL_IOCTL_DECODED ;
2016-10-03 00:59:06 +03:00
/*
* device mapper code uses % d in some places and % u in another , but
* fields themselves are declared as __u32 .
*/
tprintf ( " %s{version=%u.%u.%u " , entering ( tcp ) ? " , " : " => " ,
ioc - > version [ 0 ] , ioc - > version [ 1 ] , ioc - > version [ 2 ] ) ;
/*
* if we use a different version of ABI , do not attempt to decode
* ioctl fields
*/
if ( ioc - > version [ 0 ] ! = DM_VERSION_MAJOR ) {
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " unsupported device mapper ABI version " ) ;
2016-10-03 00:59:06 +03:00
goto skip ;
}
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " , " , * ioc , data_size ) ;
2016-10-03 00:59:06 +03:00
if ( ioc - > data_size < offsetof ( struct dm_ioctl , data ) ) {
Introduce tprintf_comment and tprints_comment functions
* defs.h (tprintf_comment, tprints_comment): New prototypes.
* strace.c (tvprintf): New function.
(tprintf): Use it.
(tprintf_comment, tprints_comment): New functions.
* aio.c (tprint_lio_opcode): Use tprints_comment.
* dm.c (dm_decode_dm_target_spec, dm_decode_dm_target_deps,
dm_decode_dm_name_list, dm_decode_dm_target_versions,
dm_decode_dm_target_msg, dm_decode_string, dm_known_ioctl): Likewise.
* futex.c (SYS_FUNC(futex)): Likewise.
* perf.c (print_perf_event_attr): Likewise.
* seccomp.c (decode_bpf_code): Likewise.
* util.c (printxvals, printxval_searchn, printflags64): Likewise.
* btrfs.c (print_u64, btrfs_print_key_type, btrfs_print_objectid,
print_key_value_internal): Likewise.
(btrfs_ioctl): Use tprints_comment and tprintf_comment.
* dirent.c (SYS_FUNC(getdents)): Likewise.
* dirent64.c (SYS_FUNC(getdents64)): Likewise.
* execve.c (printargc): Use tprintf_comment.
* tests/btrfs.c (btrfs_test_get_dev_stats_ioctl,
btrfs_test_features_ioctls): Update expected output.
2017-04-24 22:31:54 +03:00
tprints_comment ( " data_size too small " ) ;
2016-10-03 00:59:06 +03:00
goto skip ;
}
2017-04-24 22:14:41 +03:00
if ( dm_ioctl_has_params ( code ) )
2017-07-14 03:08:09 +03:00
PRINT_FIELD_U ( " , " , * ioc , data_start ) ;
2017-04-24 22:14:41 +03:00
2016-10-03 00:59:06 +03:00
dm_decode_device ( code , ioc ) ;
dm_decode_values ( tcp , code , ioc ) ;
dm_decode_flags ( ioc ) ;
switch ( code ) {
case DM_DEV_WAIT :
case DM_TABLE_STATUS :
if ( entering ( tcp ) | | syserror ( tcp ) )
break ;
dm_decode_dm_target_spec ( tcp , arg , ioc ) ;
break ;
case DM_TABLE_LOAD :
if ( exiting ( tcp ) )
break ;
dm_decode_dm_target_spec ( tcp , arg , ioc ) ;
break ;
case DM_TABLE_DEPS :
if ( entering ( tcp ) | | syserror ( tcp ) )
break ;
dm_decode_dm_target_deps ( tcp , arg , ioc ) ;
break ;
case DM_LIST_DEVICES :
if ( entering ( tcp ) | | syserror ( tcp ) )
break ;
dm_decode_dm_name_list ( tcp , arg , ioc ) ;
break ;
case DM_LIST_VERSIONS :
if ( entering ( tcp ) | | syserror ( tcp ) )
break ;
dm_decode_dm_target_versions ( tcp , arg , ioc ) ;
break ;
case DM_TARGET_MSG :
if ( entering ( tcp ) )
dm_decode_dm_target_msg ( tcp , arg , ioc ) ;
else if ( ! syserror ( tcp ) & & ioc - > flags & DM_DATA_OUT_FLAG )
dm_decode_string ( tcp , arg , ioc ) ;
break ;
case DM_DEV_RENAME :
case DM_DEV_SET_GEOMETRY :
if ( exiting ( tcp ) )
break ;
dm_decode_string ( tcp , arg , ioc ) ;
break ;
}
skip :
tprints ( " } " ) ;
2017-08-28 03:39:15 +03:00
return entering ( tcp ) ? 0 : RVAL_IOCTL_DECODED ;
2016-10-03 00:59:06 +03:00
}
int
2016-12-26 13:26:03 +03:00
dm_ioctl ( struct tcb * const tcp , const unsigned int code , const kernel_ulong_t arg )
2016-10-03 00:59:06 +03:00
{
switch ( code ) {
case DM_VERSION :
case DM_REMOVE_ALL :
case DM_LIST_DEVICES :
case DM_DEV_CREATE :
case DM_DEV_REMOVE :
case DM_DEV_RENAME :
case DM_DEV_SUSPEND :
case DM_DEV_STATUS :
case DM_DEV_WAIT :
case DM_TABLE_LOAD :
case DM_TABLE_CLEAR :
case DM_TABLE_DEPS :
case DM_TABLE_STATUS :
case DM_LIST_VERSIONS :
case DM_TARGET_MSG :
case DM_DEV_SET_GEOMETRY :
2017-09-17 04:51:51 +03:00
case DM_DEV_ARM_POLL :
2016-10-03 00:59:06 +03:00
return dm_known_ioctl ( tcp , code , arg ) ;
default :
2017-08-27 01:24:37 +03:00
return RVAL_DECODED ;
2016-10-03 00:59:06 +03:00
}
}
# else /* !(DM_VERSION_MAJOR == 4) */
int
2016-12-26 13:26:03 +03:00
dm_ioctl ( struct tcb * const tcp , const unsigned int code , const kernel_ulong_t arg )
2016-10-03 00:59:06 +03:00
{
2017-08-27 01:24:37 +03:00
return RVAL_DECODED ;
2016-10-03 00:59:06 +03:00
}
# endif /* DM_VERSION_MAJOR == 4 */
# endif /* HAVE_LINUX_DM_IOCTL_H */