From: Eugene Syromyatnikov Date: Sun, 17 Sep 2017 02:58:49 +0000 (+0200) Subject: dm: add support for event_nr in DM_LIST_DEVICES result X-Git-Tag: v4.21~103 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f36919172cae7427b8da34e2f053a5089f454a4;p=strace 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, 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, 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. --- diff --git a/NEWS b/NEWS index 550fc38e..0b30ec32 100644 --- a/NEWS +++ b/NEWS @@ -14,7 +14,7 @@ Noteworthy changes in release ?.?? (????-??-??) and BPF_OBJ_GET_INFO_BY_FD commands of bpf syscall. * Enhanced decoding of get_thread_area, memfd_create, modify_ldt, perf_event_open, reboot, set_thread_area, and shmget syscalls. - * Implemented decoding of KVM_* ioctl commands. + * Implemented decoding of KVM_* and DM_LIST_DEVICES ioctl commands. * Enhanced decoding of getsockopt and setsockopt syscalls for SOL_NETLINK level. * Enhanced decoding of BPF_MAP_CREATE command of bpf syscall. diff --git a/dm.c b/dm.c index 28863a87..32b33101 100644 --- a/dm.c +++ b/dm.c @@ -258,6 +258,7 @@ dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr, uint32_t offset = ioc->data_start; uint32_t offset_end = 0; uint32_t count; + int rc; if (ioc->data_start == ioc->data_size) return; @@ -288,8 +289,36 @@ dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr, PRINT_FIELD_DEV("{", s, dev); tprints(", name="); - printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end, - QUOTE_0_TERMINATED); + 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); + } + tprints("}"); if (!s.next)