Skip to contentSkip to conversation

your dm patch for strace

PATCH New Mikulas Patocka 5 participants 41 messages Aug 25, 2016 – Nov 11, 2016 11 messages not in the archive

Subsystems (2)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1608221155410.17400@file01.intranet.prod.int.rdu2.redhat.com

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1608231303510.7049@file01.intranet.prod.int.rdu2.redhat.com

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 20160824.233543.198328104871315294.yamato-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

#5 lore raw
Quoted 4 lines · Masatake YAMATO
Quoted 4 lines
Quoted 1 line

Are you talking about https://sourceforge.net/p/strace/mailman/message/34370586/ ?

Yes.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

The thread has apparently died without any follow-up from your side.

I didn't receive that last message, it was probably sent only to the mailing list address, not to my address.

Can I expect you will submit updated version of the patch?

Masatake YAMATO

Here I'm sending the updated device mapper strace patch with the comments addressed. (please send replies to my email address, I'm not on the strace mailing list)

Mikulas

configure.ac +1 -0
Index: strace/configure.ac
===================================================================
@@ -363,6 +363,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	elf.h
 	inttypes.h
 	linux/bsg.h
+	linux/dm-ioctl.h
 	linux/falloc.h
 	linux/fiemap.h
 	linux/filter.h
dm.c new file +351 -0

351 lines not on this page · raw message

ioctl.c +4 -0
Index: strace/ioctl.c
===================================================================
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
 	case 0x94:
 		return btrfs_ioctl(tcp, code, arg);
 #endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+	case 0xfd:
+		return dm_ioctl(tcp, code, arg);
+#endif
 	default:
 		break;
 	}
Makefile.am +1 -0
Index: strace/Makefile.am
===================================================================
@@ -97,6 +97,7 @@ strace_SOURCES =	\
 	desc.c		\
 	dirent.c	\
 	dirent64.c	\
+	dm.c		\
 	empty.h		\
 	epoll.c		\
 	evdev.c		\
defs.h +1 -0
Index: strace/defs.h
===================================================================
@@ -640,6 +640,7 @@ extern void print_struct_statfs64(struct
 
 extern void print_ifindex(unsigned int);
 
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
xlat/dm_flags.in new file +17 -0
Index: strace/xlat/dm_flags.in
===================================================================
@@ -0,0 +1,17 @@
+DM_READONLY_FLAG
+DM_SUSPEND_FLAG
+DM_PERSISTENT_DEV_FLAG
+DM_STATUS_TABLE_FLAG
+DM_ACTIVE_PRESENT_FLAG
+DM_INACTIVE_PRESENT_FLAG
+DM_BUFFER_FULL_FLAG
+DM_SKIP_BDGET_FLAG
+DM_SKIP_LOCKFS_FLAG
+DM_NOFLUSH_FLAG
+DM_QUERY_INACTIVE_TABLE_FLAG
+DM_UEVENT_GENERATED_FLAG
+DM_UUID_FLAG
+DM_SECURE_DATA_FLAG
+DM_DATA_OUT_FLAG
+DM_DEFERRED_REMOVE
+DM_INTERNAL_SUSPEND_FLAG

------------------------------------------------------------------------------

A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1608250823130.24332-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]

#7 lore raw
Quoted 141 lines · Mikulas Patocka
Quoted 4 lines · Masatake YAMATO
Quoted 4 lines
Quoted 1 line

Are you talking about https://sourceforge.net/p/strace/mailman/message/34370586/ ?

Yes.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

The thread has apparently died without any follow-up from your side.

I didn't receive that last message, it was probably sent only to the mailing list address, not to my address.

Can I expect you will submit updated version of the patch?

Masatake YAMATO

Here I'm sending the updated device mapper strace patch with the comments addressed. (please send replies to my email address, I'm not on the strace mailing list)

Mikulas

Index: strace/configure.ac
===================================================================

configure.ac +1 -0
@@ -363,6 +363,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	elf.h
 	inttypes.h
 	linux/bsg.h
+	linux/dm-ioctl.h
 	linux/falloc.h
 	linux/fiemap.h
 	linux/filter.h

Index: strace/dm.c
===================================================================

dm.c new file +103 -0
@@ -0,0 +1,351 @@
+#include "defs.h"
+
+#ifdef HAVE_LINUX_DM_IOCTL_H
+
+#include <sys/ioctl.h>
+#include <linux/dm-ioctl.h>
+
+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:
+		if (ioc->dev)
+			tprintf(", dev=makedev(%u, %u)",
+				major(ioc->dev), minor(ioc->dev));
+		if (ioc->name[0]) {
+			tprints(", name=");
+			print_quoted_string(ioc->name, DM_NAME_LEN,
+					    QUOTE_0_TERMINATED);
+		}
+		if (ioc->uuid[0]) {
+			tprints(", uuid=");
+			print_quoted_string(ioc->uuid, DM_UUID_LEN,
+					    QUOTE_0_TERMINATED);
+		}
+		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:
+			tprintf(", target_count=%"PRIu32"",
+				ioc->target_count);
+			break;
+		case DM_DEV_SUSPEND:
+			if (ioc->flags & DM_SUSPEND_FLAG)
+				break;
+		case DM_DEV_RENAME:
+		case DM_DEV_REMOVE:
+		case DM_DEV_WAIT:
+			tprintf(", event_nr=%"PRIu32"",
+				ioc->event_nr);
+			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:
+			tprintf(", target_count=%"PRIu32"",
+				ioc->target_count);
+			tprintf(", open_count=%"PRIu32"",
+				ioc->open_count);
+			tprintf(", event_nr=%"PRIu32"",
+				ioc->event_nr);
+			break;
+		}
+	}
+}
+
+#include "xlat/dm_flags.h"
+
+static void
+dm_decode_flags(const struct dm_ioctl *ioc)
+{
+	tprints(", flags=");
+	printflags(dm_flags, ioc->flags, "DM_???");
+}
+
+static void
+dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
+			 const char *extra, uint32_t extra_size)
+{
+	uint32_t i;
+	uint32_t offset = ioc->data_start;
+	for (i = 0; i < ioc->target_count; i++) {
+		if (offset + (uint32_t)sizeof(struct dm_target_spec) >= offset &&
+		    offset + (uint32_t)sizeof(struct dm_target_spec) < extra_size) {
+			const struct dm_target_spec *s =
+				(const struct dm_target_spec *)(extra + offset);
+			tprintf(", {sector_start=%"PRIu64", length=%"PRIu64"",
+				(uint64_t)s->sector_start, (uint64_t)s->length);
+			if (!entering(tcp))
+				tprintf(", status=%"PRId32"", s->status);
+			tprints(", target_type=");
+			print_quoted_string(s->target_type, DM_MAX_TYPE_NAME,
+					    QUOTE_0_TERMINATED);

dm.c line 113

Quoted 10 lines
dm.c new file +10 -0
+			tprints(", string=");
+			print_quoted_string((const char *)(s + 1), extra_size -
+					    (offset +
+					    sizeof(struct dm_target_spec)),
+					    QUOTE_0_TERMINATED);
+			tprintf("}");
+			if (entering(tcp))
+				offset = offset + s->next;
+			else
+				offset = ioc->data_start + s->next;

This code trusts s->next; unfortunately, strace cannot trust syscall arguments, otherwise anything may happen, e.g.

$ cat ioctl_dm.c
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
int main(void)
{
	struct {
		struct dm_ioctl ioc;
		struct dm_target_spec spec;
		int i;
	} s = {
		.spec = { 0 },
		.ioc = {
			.version[0] = DM_VERSION_MAJOR,
			.data_size = sizeof(s),
			.data_start = sizeof(s.ioc),
			.target_count = -1U
		}
	};
	return !ioctl(-1, DM_TABLE_LOAD, &s);
}
$ strace -veioctl ./ioctl_dm

btw, this parser lacks tests. How one can easily verify that it works correctly? For example how a test for strace ioctl parser may look like see tests/ioctl_* files.

Signature · 1 line
ldv

------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohodev2dev

_______________________________________________
Strace-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

A message that is not in the archive (sent off-list or not yet received): 20160912171029.GA5263-u2l5PoMzF/[email protected]

#9 lore raw
Quoted 31 lines · Dmitry V. Levin

Review

Quoted 5 lines
(quoted diff) +5 -0
+			tprintf("}");
+			if (entering(tcp))
+				offset = offset + s->next;
+			else
+				offset = ioc->data_start + s->next;

This code trusts s->next; unfortunately, strace cannot trust syscall arguments, otherwise anything may happen, e.g.

$ cat ioctl_dm.c
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
int main(void)
{
	struct {
		struct dm_ioctl ioc;
		struct dm_target_spec spec;
		int i;
	} s = {
		.spec = { 0 },
		.ioc = {
			.version[0] = DM_VERSION_MAJOR,
			.data_size = sizeof(s),
			.data_start = sizeof(s.ioc),
			.target_count = -1U
		}
	};
	return !ioctl(-1, DM_TABLE_LOAD, &s);
}
$ strace -veioctl ./ioctl_dm
Quoted 7 lines

btw, this parser lacks tests. How one can easily verify that it works correctly? For example how a test for strace ioctl parser may look like see tests/ioctl_* files.

Signature · 1 line
ldv

Here I'm sending new patch. It fixes the possible loop with s->next and adds tests:

 Makefile.am         |    1 
 configure.ac        |    1 
 defs.h              |    1 
 dm.c                |  356 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 ioctl.c             |    4 
 tests/Makefile.am   |    2 
 tests/ioctl_dm.c    |   78 +++++++++++
 tests/ioctl_dm.test |   12 +
 xlat/dm_flags.in    |   17 ++
 9 files changed, 472 insertions(+)
Makefile.am +1 -0
Index: strace/Makefile.am
===================================================================
@@ -97,6 +97,7 @@ strace_SOURCES =	\
 	desc.c		\
 	dirent.c	\
 	dirent64.c	\
+	dm.c		\
 	empty.h		\
 	epoll.c		\
 	evdev.c		\
configure.ac +1 -0
Index: strace/configure.ac
===================================================================
@@ -354,6 +354,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	elf.h
 	inttypes.h
 	linux/bsg.h
+	linux/dm-ioctl.h
 	linux/dqblk_xfs.h
 	linux/falloc.h
 	linux/fiemap.h
defs.h +1 -0
Index: strace/defs.h
===================================================================
@@ -640,6 +640,7 @@ extern void print_struct_statfs64(struct
 
 extern void print_ifindex(unsigned int);
 
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
dm.c new file +356 -0

356 lines not on this page · raw message

ioctl.c +4 -0
Index: strace/ioctl.c
===================================================================
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
 	case 0x94:
 		return btrfs_ioctl(tcp, code, arg);
 #endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+	case 0xfd:
+		return dm_ioctl(tcp, code, arg);
+#endif
 	default:
 		break;
 	}
tests/Makefile.am +2 -0
Index: strace/tests/Makefile.am
===================================================================
@@ -161,6 +161,7 @@ check_PROGRAMS = \
 	inet-cmsg \
 	ioctl \
 	ioctl_block \
+	ioctl_dm \
 	ioctl_evdev \
 	ioctl_evdev-v \
 	ioctl_mtd \
@@ -503,6 +504,7 @@ DECODER_TESTS = \
 	inet-cmsg.test \
 	ioctl.test \
 	ioctl_block.test \
+	ioctl_dm.test \
 	ioctl_evdev.test \
 	ioctl_evdev-v.test \
 	ioctl_mtd.test \
tests/ioctl_dm.c new file +78 -0

78 lines not on this page · raw message

tests/ioctl_dm.test new file +12 -0
Index: strace/tests/ioctl_dm.test
===================================================================
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -veioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"
xlat/dm_flags.in new file +17 -0
Index: strace/xlat/dm_flags.in
===================================================================
@@ -0,0 +1,17 @@
+DM_READONLY_FLAG
+DM_SUSPEND_FLAG
+DM_PERSISTENT_DEV_FLAG
+DM_STATUS_TABLE_FLAG
+DM_ACTIVE_PRESENT_FLAG
+DM_INACTIVE_PRESENT_FLAG
+DM_BUFFER_FULL_FLAG
+DM_SKIP_BDGET_FLAG
+DM_SKIP_LOCKFS_FLAG
+DM_NOFLUSH_FLAG
+DM_QUERY_INACTIVE_TABLE_FLAG
+DM_UEVENT_GENERATED_FLAG
+DM_UUID_FLAG
+DM_SECURE_DATA_FLAG
+DM_DATA_OUT_FLAG
+DM_DEFERRED_REMOVE
+DM_INTERNAL_SUSPEND_FLAG

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot

A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1610021751280.29417-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]

#11 lore raw

I tested the patch and it works fine.
Could you add following patch if you approve?

commit bae7528fa92283726caac1ec7a6c306274f8899d

Author: Masatake YAMATO <[email protected]>
Date:   Mon Aug 22 17:44:55 2016 +0900

dm-ioctl: add a lvm private flag

When I run "dmsetup ls" under dm-ioctl patched strace, "strange DM_???" are found in its output.

# ./strace -e ioctl dmsetup ls > /dev/null
ioctl(3, DM_VERSION, {version=4.0.0, flags=0x4 /* DM_??? */}, ... ioctl(3, DM_LIST_DEVICES, {version=4.0.0, flags=0x4 /* DM_??? */}, ...
...

Associated definion for DM_??? is in lvm2 source tree. This commit imports the definion to dm-ioctl list.

xlat/dm_flags.in +2 -0
index ab4285c..1e7132b 100644
@@ -1,5 +1,7 @@
 DM_READONLY_FLAG
 DM_SUSPEND_FLAG
+/* Defined in lvm2/libdm/ioctl/libdm-iface.c */
+DM_EXISTS_FLAG 0x00000004
 DM_PERSISTENT_DEV_FLAG
 DM_STATUS_TABLE_FLAG
 DM_ACTIVE_PRESENT_FLAG

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot

A message that is not in the archive (sent off-list or not yet received): 20161005.192828.566127461630656590.yamato-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

#13 lore raw

cover Some possible additions to the DM ioctl patch for strace

Hello.

I've took the liberty to look at the patch and I'd like to propose some changes to it. Can you please review them from the DM side of things? I'm not quite sure I've understood all the specifics of the interface correctly, it's quite peculiar.

I'm also preparing a patch for the DM ioctl decoder test, but it's not ready yet.

Eugene Syromyatnikov (21):
tests/ioctl_dm: Formatting
dm: whitespace fixes
tests: Working around bounds check
dm: Minor output tweaks
xlat: Add values for dm_flags
dm: Some future-proofing by means of compile-time DM_VERSION_MAJOR
check
dm: Add definitions for ioctl commands not implemented initially
dm: Use static constants for offset sizes
dm: Remove char * cast
dm: use => instead of , for splitting output structure from input
dm: Compare entering field values with exiting ones
dm: Add inttypes.h, include reorder
dm: Move printing of dm_ioctl fields before allocation of extra data
dm: replace abbrev branching with goto
dm: Additional data_size/data_start checks
dm: Add comment regarding intended fall-through in switch statement
dm: Add data_size and data_offset fields to output tests/ioctl_dm: Allow passing size and data_start to init_s
dm: Add check whether command uses parameters
dm: Fix printing of version field
dm: rewrite structure decoding

 dm.c             |  549 ++++++++++++++++++++++++++++++++++++------------------
 tests/ioctl_dm.c |   79 +++++---
 xlat/dm_flags.in |   36 ++--
 3 files changed, 442 insertions(+), 222 deletions(-)
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#14 lore raw

PATCH 1/21 tests/ioctl_dm: Formatting

In reply to a message not in the archive
---
 tests/ioctl_dm.c |   42 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 35 insertions(+), 7 deletions(-)
tests/ioctl_dm.c +35 -7
index f4c3c8b..a5945ae 100644
@@ -40,38 +40,66 @@ main(void)
 	s.ioc.data_size = sizeof(s.ioc);
 	s.ioc.data_start = 0;
 	ioctl(-1, DM_VERSION, &s);
-	printf("ioctl(-1, DM_VERSION, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_VERSION, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
 	s.ioc.target_count = 1;
 	s.u.ts.target_spec.sector_start = 0x10;
 	s.u.ts.target_spec.length = 0x20;
-	s.u.ts.target_spec.next = sizeof(s.u.ts.target_spec) + sizeof(s.u.ts.target_params);
+	s.u.ts.target_spec.next =
+		sizeof(s.u.ts.target_spec) + sizeof(s.u.ts.target_params);
 	strcpy(s.u.ts.target_spec.target_type, "tgt");
 	strcpy(s.u.ts.target_params, "tparams");
 	ioctl(-1, DM_TABLE_LOAD, &s);
-	printf("ioctl(-1, DM_TABLE_LOAD, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", target_count=1, flags=0, {sector_start=16, length=32, target_type=\"tgt\", string=\"tparams\"}}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", target_count=1, flags=0, {sector_start=16, "
+	       "length=32, target_type=\"tgt\", string=\"tparams\"}}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
 	s.u.tm.target_msg.sector = 0x1234;
 	strcpy(s.u.tm.target_msg.message, "tmsg");
 	ioctl(-1, DM_TARGET_MSG, &s);
-	printf("ioctl(-1, DM_TARGET_MSG, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
 	strcpy(s.u.string, "10 20 30 40");
 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
-	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, string=\"10 20 30 40\"}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0, string=\"10 20 30 40\"}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
 	strcpy(s.u.string, "new-name");
 	ioctl(-1, DM_DEV_RENAME, &s);
-	printf("ioctl(-1, DM_DEV_RENAME, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_DEV_RENAME, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
 	s.ioc.target_count = -1U;
 	ioctl(-1, DM_TABLE_LOAD, &s);
-	printf("ioctl(-1, DM_TABLE_LOAD, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", target_count=4294967295, flags=0, {sector_start=0, length=0, target_type=\"\", string=\"\"}, misplaced struct dm_target_spec}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", target_count=4294967295, flags=0, "
+	       "{sector_start=0, length=0, target_type=\"\", string=\"\"}, "
+	       "misplaced struct dm_target_spec}, "
+	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
+	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	puts("+++ exited with 0 +++");
 	return 0;
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#15 lore raw

PATCH 2/21 dm: whitespace fixes

In reply to a message not in the archive
---
 dm.c |   87 +++++++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 52 insertions(+), 35 deletions(-)
dm.c +52 -35
index 33a3972..d81983d 100644
@@ -2,8 +2,8 @@
 
 #ifdef HAVE_LINUX_DM_IOCTL_H
 
-#include <sys/ioctl.h>
-#include <linux/dm-ioctl.h>
+# include <sys/ioctl.h>
+# include <linux/dm-ioctl.h>
 
 static void
 dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc)
@@ -38,7 +38,7 @@ dm_decode_values(struct tcb *tcp, const unsigned int code,
 	if (entering(tcp)) {
 		switch (code) {
 		case DM_TABLE_LOAD:
-			tprintf(", target_count=%"PRIu32"",
+			tprintf(", target_count=%" PRIu32,
 				ioc->target_count);
 			break;
 		case DM_DEV_SUSPEND:
@@ -47,7 +47,7 @@ dm_decode_values(struct tcb *tcp, const unsigned int code,
 		case DM_DEV_RENAME:
 		case DM_DEV_REMOVE:
 		case DM_DEV_WAIT:
-			tprintf(", event_nr=%"PRIu32"",
+			tprintf(", event_nr=%" PRIu32,
 				ioc->event_nr);
 			break;
 		}
@@ -63,11 +63,11 @@ dm_decode_values(struct tcb *tcp, const unsigned int code,
 		case DM_TABLE_DEPS:
 		case DM_TABLE_STATUS:
 		case DM_TARGET_MSG:
-			tprintf(", target_count=%"PRIu32"",
+			tprintf(", target_count=%" PRIu32,
 				ioc->target_count);
-			tprintf(", open_count=%"PRIu32"",
+			tprintf(", open_count=%" PRIu32,
 				ioc->open_count);
-			tprintf(", event_nr=%"PRIu32"",
+			tprintf(", event_nr=%" PRIu32,
 				ioc->event_nr);
 			break;
 		}
@@ -89,21 +89,23 @@ dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
 {
 	uint32_t i;
 	uint32_t offset = ioc->data_start;
+
 	for (i = 0; i < ioc->target_count; i++) {
-		if (offset + (uint32_t)sizeof(struct dm_target_spec) >= offset &&
-		    offset + (uint32_t)sizeof(struct dm_target_spec) < extra_size) {
+		if (offset + (uint32_t) sizeof(struct dm_target_spec) >= offset &&
+		    offset + (uint32_t) sizeof(struct dm_target_spec) < extra_size) {
 			uint32_t new_offset;
 			const struct dm_target_spec *s =
-				(const struct dm_target_spec *)(extra + offset);
-			tprintf(", {sector_start=%"PRIu64", length=%"PRIu64"",
-				(uint64_t)s->sector_start, (uint64_t)s->length);
+				(const struct dm_target_spec *) (extra + offset);
+			tprintf(", {sector_start=%" PRIu64 ", length=%" PRIu64,
+				(uint64_t) s->sector_start,
+				(uint64_t) s->length);
 			if (!entering(tcp))
-				tprintf(", status=%"PRId32"", s->status);
+				tprintf(", status=%" PRId32, s->status);
 			tprints(", target_type=");
 			print_quoted_string(s->target_type, DM_MAX_TYPE_NAME,
 					    QUOTE_0_TERMINATED);
 			tprints(", string=");
-			print_quoted_string((const char *)(s + 1), extra_size -
+			print_quoted_string((const char *) (s + 1), extra_size -
 					    (offset +
 					    sizeof(struct dm_target_spec)),
 					    QUOTE_0_TERMINATED);
@@ -112,7 +114,8 @@ dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
 				new_offset = offset + s->next;
 			else
 				new_offset = ioc->data_start + s->next;
-			if (new_offset <= offset + (uint32_t)sizeof(struct dm_target_spec))
+			if (new_offset <= offset +
+			    (uint32_t) sizeof(struct dm_target_spec))
 				goto misplaced;
 			offset = new_offset;
 		} else {
@@ -128,13 +131,15 @@ dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra,
 			 uint32_t extra_size)
 {
 	uint32_t offset = ioc->data_start;
-	if (offset + (uint32_t)offsetof(struct dm_target_deps, dev) >= offset &&
-	    offset + (uint32_t)offsetof(struct dm_target_deps, dev) <= extra_size) {
+	if (offset + (uint32_t) offsetof(struct dm_target_deps, dev) >= offset &&
+	    offset + (uint32_t) offsetof(struct dm_target_deps, dev) <= extra_size) {
+
 		uint32_t i;
 		uint32_t space = (extra_size - (offset +
 			offsetof(struct dm_target_deps, dev))) / sizeof(__u64);
 		const struct dm_target_deps *s =
-			(const struct dm_target_deps *)(extra + offset);
+			(const struct dm_target_deps *) (extra + offset);
+
 		if (s->count > space)
 			goto misplaced;
 		tprints(", deps={");
@@ -154,21 +159,25 @@ dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
 		       uint32_t extra_size)
 {
 	uint32_t offset = ioc->data_start;
+
 	while (1) {
-		if (offset + (uint32_t)offsetof(struct dm_name_list, name) >= offset &&
-		    offset + (uint32_t)offsetof(struct dm_name_list, name) < extra_size) {
+		if (offset + (uint32_t) offsetof(struct dm_name_list, name) >= offset &&
+		    offset + (uint32_t) offsetof(struct dm_name_list, name) < extra_size) {
 			const struct dm_name_list *s =
-				(const struct dm_name_list *)(extra + offset);
+				(const struct dm_name_list *) (extra + offset);
+
 			if (!s->dev)
 				break;
-			tprintf(", {dev=makedev(%u, %u), name=", major(s->dev), minor(s->dev));
+			tprintf(", {dev=makedev(%u, %u), name=", major(s->dev),
+				minor(s->dev));
 			print_quoted_string(s->name, extra_size - (offset +
 					    offsetof(struct dm_name_list,
 					    name)), QUOTE_0_TERMINATED);
 			tprints("}");
 			if (!s->next)
 				break;
-			if (offset + s->next <= offset + (uint32_t)offsetof(struct dm_name_list, name))
+			if (offset + s->next <= offset +
+			    (uint32_t) offsetof(struct dm_name_list, name))
 				goto misplaced;
 			offset = offset + s->next;
 		} else {
@@ -184,22 +193,25 @@ dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra,
 			     uint32_t extra_size)
 {
 	uint32_t offset = ioc->data_start;
+
 	while (1) {
-		if (offset + (uint32_t)offsetof(struct dm_target_versions, name) >=
+		if (offset + (uint32_t) offsetof(struct dm_target_versions, name) >=
 		    offset &&
-		    offset + (uint32_t)offsetof(struct dm_target_versions, name) <
+		    offset + (uint32_t) offsetof(struct dm_target_versions, name) <
 		    extra_size) {
 			const struct dm_target_versions *s =
 			    (const struct dm_target_versions *)(extra + offset);
+
 			tprints(", {name=");
 			print_quoted_string(s->name, extra_size - (offset +
 					    offsetof(struct dm_target_versions,
 					    name)), QUOTE_0_TERMINATED);
-			tprintf(", version=%"PRIu32".%"PRIu32".%"PRIu32"}",
+			tprintf(", version=%" PRIu32 ".%" PRIu32 ".%" PRIu32 "}",
 				s->version[0], s->version[1], s->version[2]);
 			if (!s->next)
 				break;
-			if (offset + s->next <= offset + (uint32_t)offsetof(struct dm_target_versions, name))
+			if (offset + s->next <= offset +
+			    (uint32_t) offsetof(struct dm_target_versions, name))
 				goto misplaced;
 			offset = offset + s->next;
 		} else {
@@ -215,11 +227,14 @@ dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
 			uint32_t extra_size)
 {
 	uint32_t offset = ioc->data_start;
-	if (offset + (uint32_t)offsetof(struct dm_target_msg, message) >= offset &&
-	    offset + (uint32_t)offsetof(struct dm_target_msg, message) < extra_size) {
+
+	if (offset + (uint32_t) offsetof(struct dm_target_msg, message) >= offset &&
+	    offset + (uint32_t) offsetof(struct dm_target_msg, message) < extra_size) {
 		const struct dm_target_msg *s =
-			(const struct dm_target_msg *)(extra + offset);
-		tprintf(", {sector=%"PRIu64", message=", (uint64_t)s->sector);
+			(const struct dm_target_msg *) (extra + offset);
+
+		tprintf(", {sector=%" PRIu64 ", message=",
+			(uint64_t) s->sector);
 		print_quoted_string(s->message, extra_size -
 				    offsetof(struct dm_target_msg, message),
 				    QUOTE_0_TERMINATED);
@@ -234,6 +249,7 @@ dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
 		 uint32_t extra_size)
 {
 	uint32_t offset = ioc->data_start;
+
 	if (offset < extra_size) {
 		tprints(", string=");
 		print_quoted_string(extra + offset, extra_size - offset,
@@ -250,7 +266,7 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	char *extra = NULL;
 	uint32_t extra_size = 0;
 
-	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *)&ioc) < 0)
+	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *) &ioc) < 0)
 		return 0;
 	tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1],
 		ioc.version[2]);
@@ -276,7 +292,8 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	dm_decode_device(code, &ioc);
 	dm_decode_values(tcp, code, &ioc);
 	dm_decode_flags(&ioc);
-	if (!abbrev(tcp)) switch (code) {
+	if (!abbrev(tcp))
+		switch (code) {
 		case DM_DEV_WAIT:
 		case DM_TABLE_STATUS:
 			if (entering(tcp) || syserror(tcp))
@@ -308,7 +325,7 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 				dm_decode_dm_target_msg(&ioc, extra,
 							extra_size);
 			} else if (!syserror(tcp) &&
-				   ioc.flags & DM_DATA_OUT_FLAG) {
+			    ioc.flags & DM_DATA_OUT_FLAG) {
 				dm_decode_string(&ioc, extra, extra_size);
 			}
 			break;
@@ -318,7 +335,7 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 				break;
 			dm_decode_string(&ioc, extra, extra_size);
 			break;
-	}
+		}
 
  skip:
 	tprints("}");
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#16 lore raw

PATCH 3/21 tests: Working around bounds check

In reply to a message not in the archive

When building with -Wp,-D_FORTIFY_SOURCE=2, dompiler produces the following warning:

In file included from /usr/include/string.h:638:0,

                 from ioctl_dm.c:4:

In function ‘strcpy’,
inlined from ‘main’ at ioctl_dm.c:57:8:
/usr/include/bits/string3.h:104:3: warning: call to __builtin___strcpy_chk will always overflow destination buffer [enabled by default]
return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
^

And later it aborts:

[  200s] FAIL: ioctl_dm
[  200s] ==============
[  200s]
[  200s] + ../strace -V
[  200s] + TIMEOUT='timeout -s 9 60'
[  200s] + timeout -s 9 60 true
[  200s] + exec timeout -s 9 60 ./ioctl_dm.test
[  200s] + run_prog
[  200s] + '[' 0 -eq 0 ']'
[  200s] + set -- ./ioctl_dm
[  200s] + args=./ioctl_dm
[  200s] + ./ioctl_dm
[  200s] *** buffer overflow detected ***: ./ioctl_dm terminated
[  200s] ======= Backtrace: =========
[  200s] /lib64/libc.so.6(__fortify_fail+0x37)[0x7fbc8fa1acb7]
[  200s] /lib64/libc.so.6(+0x10be80)[0x7fbc8fa18e80]
[  200s] ./ioctl_dm[0x400616]
[  200s] /lib64/libc.so.6(__libc_start_main+0xf5)[0x7fbc8f92eaf5]
[  200s] ./ioctl_dm[0x400739]
[  200s] ======= Memory map: ========
[  200s] 00400000-00401000 r-xp 00000000 08:00 84792                              /home/abuild/rpmbuild/BUILD/strace-4.13.0.260.af086/tests/ioctl_dm
[  200s] 00601000-00602000 r--p 00001000 08:00 84792                              /home/abuild/rpmbuild/BUILD/strace-4.13.0.260.af086/tests/ioctl_dm
[  200s] 00602000-00603000 rw-p 00002000 08:00 84792                              /home/abuild/rpmbuild/BUILD/strace-4.13.0.260.af086/tests/ioctl_dm
[  200s] 02244000-02265000 rw-p 00000000 00:00 0                                  [heap]
[  200s] 7fbc8f6f5000-7fbc8f70a000 r-xp 00000000 08:00 131341                     /usr/lib64/libgcc_s-4.8.2-20140120.so.1
[  200s] 7fbc8f70a000-7fbc8f909000 ---p 00015000 08:00 131341                     /usr/lib64/libgcc_s-4.8.2-20140120.so.1
[  200s] 7fbc8f909000-7fbc8f90a000 r--p 00014000 08:00 131341                     /usr/lib64/libgcc_s-4.8.2-20140120.so.1
[  200s] 7fbc8f90a000-7fbc8f90b000 rw-p 00015000 08:00 131341                     /usr/lib64/libgcc_s-4.8.2-20140120.so.1
[  200s] 7fbc8f90d000-7fbc8fac3000 r-xp 00000000 08:00 131350                     /usr/lib64/libc-2.17.so
[  200s] 7fbc8fac3000-7fbc8fcc3000 ---p 001b6000 08:00 131350                     /usr/lib64/libc-2.17.so
[  200s] 7fbc8fcc3000-7fbc8fcc7000 r--p 001b6000 08:00 131350                     /usr/lib64/libc-2.17.so
[  200s] 7fbc8fcc7000-7fbc8fcc9000 rw-p 001ba000 08:00 131350                     /usr/lib64/libc-2.17.so
[  200s] 7fbc8fcc9000-7fbc8fcce000 rw-p 00000000 00:00 0
[  200s] 7fbc8fcd5000-7fbc8fcf6000 r-xp 00000000 08:00 131343                     /usr/lib64/ld-2.17.so
[  200s] 7fbc8fef1000-7fbc8fef5000 rw-p 00000000 00:00 0
[  200s] 7fbc8fef5000-7fbc8fef6000 r--p 00020000 08:00 131343                     /usr/lib64/ld-2.17.so
[  200s] 7fbc8fef6000-7fbc8fef7000 rw-p 00021000 08:00 131343                     /usr/lib64/ld-2.17.so
[  200s] 7fbc8fef7000-7fbc8fef9000 rw-p 00000000 00:00 0
[  200s] 7ffe9b7e3000-7ffe9b806000 rw-p 00000000 00:00 0                          [stack]
[  200s] 7ffe9b84d000-7ffe9b84f000 r--p 00000000 00:00 0                          [vvar]
[  200s] 7ffe9b84f000-7ffe9b851000 r-xp 00000000 00:00 0                          [vdso]
[  200s] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
[  200s] ./init.sh: line 53: 15162 Aborted                 "$@"
[  200s] + rc=134
[  200s] + '[' 134 -eq 77 ']'
[  200s] + fail_ './ioctl_dm failed with code 134'
[  200s] + warn_ 'ioctl_dm.test: failed test: ./ioctl_dm failed with code 134'
[  200s] + printf '%s\n' 'ioctl_dm.test: failed test: ./ioctl_dm failed with code 134'
[  200s] ioctl_dm.test: failed test: ./ioctl_dm failed with code 134
[  200s] + exit 1

It is due the fact that message field is 0-element array. Worked around by copying to string field with appropriate offset.

---
 tests/ioctl_dm.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
tests/ioctl_dm.c +2 -1
index a5945ae..cb6dd97 100644
@@ -64,7 +64,8 @@ main(void)
 
 	init_s();
 	s.u.tm.target_msg.sector = 0x1234;
-	strcpy(s.u.tm.target_msg.message, "tmsg");
+	strcpy(s.u.string + offsetof(struct dm_target_msg, message),
+		"tmsg");
 	ioctl(-1, DM_TARGET_MSG, &s);
 	printf("ioctl(-1, DM_TARGET_MSG, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
Signature · 10 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel
#17 lore raw

PATCH 4/21 dm: Minor output tweaks

In reply to a message not in the archive

Trying to make it more C-like and in line with common practices regarding structure printing.

---
 dm.c             |   21 +++++++++++++--------
 tests/ioctl_dm.c |    2 +-
 2 files changed, 14 insertions(+), 9 deletions(-)
dm.c +13 -8
index d81983d..ebdfc44 100644
@@ -120,7 +120,7 @@ dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
 			offset = new_offset;
 		} else {
 misplaced:
-			tprints(", misplaced struct dm_target_spec");
+			tprints(", /* misplaced struct dm_target_spec */ ...");
 			break;
 		}
 	}
@@ -150,7 +150,7 @@ dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra,
 		tprints("}");
 	} else {
  misplaced:
-		tprints(", misplaced struct dm_target_deps");
+		tprints(", /* misplaced struct dm_target_deps */ ...");
 	}
 }
 
@@ -182,7 +182,7 @@ dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
 			offset = offset + s->next;
 		} else {
  misplaced:
-			tprints(", misplaced struct dm_name_list");
+			tprints(", /* misplaced struct dm_name_list */ ...");
 			break;
 		}
 	}
@@ -216,7 +216,8 @@ dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra,
 			offset = offset + s->next;
 		} else {
  misplaced:
-			tprints(", misplaced struct dm_target_versions");
+			tprints(", /* misplaced struct dm_target_versions */ "
+				"...");
 			break;
 		}
 	}
@@ -240,7 +241,7 @@ dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
 				    QUOTE_0_TERMINATED);
 		tprints("}");
 	} else {
-		tprints(", misplaced struct dm_target_msg");
+		tprints(", /* misplaced struct dm_target_msg */");
 	}
 }
 
@@ -255,7 +256,7 @@ dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
 		print_quoted_string(extra + offset, extra_size - offset,
 				    QUOTE_0_TERMINATED);
 	} else {
-		tprints(", misplaced string");
+		tprints(", /* misplaced string */");
 	}
 }
 
@@ -275,8 +276,10 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	 * if we use a different version of ABI, do not attempt to decode
 	 * ioctl fields
 	 */
-	if (ioc.version[0] != DM_VERSION_MAJOR)
+	if (ioc.version[0] != DM_VERSION_MAJOR) {
+		tprints(", /* Unsupported device mapper ABI version */ ...");
 		goto skip;
+	}
 
 	if (ioc.data_size > sizeof(ioc)) {
 		extra = malloc(ioc.data_size);
@@ -292,7 +295,9 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	dm_decode_device(code, &ioc);
 	dm_decode_values(tcp, code, &ioc);
 	dm_decode_flags(&ioc);
-	if (!abbrev(tcp))
+	if (abbrev(tcp))
+		tprints(", ...");
+	else
 		switch (code) {
 		case DM_DEV_WAIT:
 		case DM_TABLE_STATUS:
tests/ioctl_dm.c +1 -1
index cb6dd97..ba484ee 100644
@@ -98,7 +98,7 @@ main(void)
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", target_count=4294967295, flags=0, "
 	       "{sector_start=0, length=0, target_type=\"\", string=\"\"}, "
-	       "misplaced struct dm_target_spec}, "
+	       "/* misplaced struct dm_target_spec */ ...}, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#18 lore raw

PATCH 5/21 xlat: Add values for dm_flags

In reply to a message not in the archive

Otherwise build fails on some old distros which lack DM_DATA_OUT_FLAG and other flags (excerpt from RHEL 5 build log):

[   66s] dm.c: In function 'dm_known_ioctl':
[   66s] dm.c:311: error: 'DM_DATA_OUT_FLAG' undeclared (first use in this function)
[   66s] dm.c:311: error: (Each undeclared identifier is reported only once
[   66s] dm.c:311: error: for each function it appears in.)

Curiously, EXISTS flags had been present in v1 of DM interface, but was removed in v4.

* xlat/dm_flags.in: Add values for DM_*_FLAG constants (obtained from <linux/dm-ioctl.h>).

---
 xlat/dm_flags.in |   36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)
xlat/dm_flags.in +18 -18
index 1e7132b..fa734c8 100644
@@ -1,19 +1,19 @@
-DM_READONLY_FLAG
-DM_SUSPEND_FLAG
+DM_READONLY_FLAG             (1 << 0)
+DM_SUSPEND_FLAG              (1 << 1)
 /* Defined in lvm2/libdm/ioctl/libdm-iface.c */
-DM_EXISTS_FLAG 0x00000004
-DM_PERSISTENT_DEV_FLAG
-DM_STATUS_TABLE_FLAG
-DM_ACTIVE_PRESENT_FLAG
-DM_INACTIVE_PRESENT_FLAG
-DM_BUFFER_FULL_FLAG
-DM_SKIP_BDGET_FLAG
-DM_SKIP_LOCKFS_FLAG
-DM_NOFLUSH_FLAG
-DM_QUERY_INACTIVE_TABLE_FLAG
-DM_UEVENT_GENERATED_FLAG
-DM_UUID_FLAG
-DM_SECURE_DATA_FLAG
-DM_DATA_OUT_FLAG
-DM_DEFERRED_REMOVE
-DM_INTERNAL_SUSPEND_FLAG
+DM_EXISTS_FLAG               (1 << 2)
+DM_PERSISTENT_DEV_FLAG       (1 << 3)
+DM_STATUS_TABLE_FLAG         (1 << 4)
+DM_ACTIVE_PRESENT_FLAG       (1 << 5)
+DM_INACTIVE_PRESENT_FLAG     (1 << 6)
+DM_BUFFER_FULL_FLAG          (1 << 8)
+DM_SKIP_BDGET_FLAG           (1 << 9)
+DM_SKIP_LOCKFS_FLAG          (1 << 10)
+DM_NOFLUSH_FLAG              (1 << 11)
+DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12)
+DM_UEVENT_GENERATED_FLAG     (1 << 13)
+DM_UUID_FLAG                 (1 << 14)
+DM_SECURE_DATA_FLAG          (1 << 15)
+DM_DATA_OUT_FLAG             (1 << 16)
+DM_DEFERRED_REMOVE           (1 << 17)
+DM_INTERNAL_SUSPEND_FLAG     (1 << 18)
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#19 lore raw

PATCH 6/21 dm: Some future-proofing by means of compile-time DM_VERSION_MAJOR check

In reply to a message not in the archive

* dm.c: Add check whether DM_VERSION_MAJOR equals to 4, provide empty dm_ioctl if check fails.

---
 dm.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
dm.c +12 -1
index ebdfc44..79bb7c7 100644
@@ -5,6 +5,8 @@
 # include <sys/ioctl.h>
 # include <linux/dm-ioctl.h>
 
+# if DM_VERSION_MAJOR == 4
+
 static void
 dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc)
 {
@@ -375,4 +377,13 @@ dm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	}
 }
 
-#endif
+# else /* !(DM_VERSION_MAJOR == 4) */
+
+int
+dm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+	return 0;
+}
+
+# endif /* DM_VERSION_MAJOR == 4 */
+#endif /* HAVE_LINUX_DM_IOCTL_H */
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#20 lore raw

PATCH 7/21 dm: Add definitions for ioctl commands not implemented initially

In reply to a message not in the archive

dm.c [!DM_LIST_VERSIONS] (DM_LIST_VERSIONS): New definition. [!DM_TARGET_MSG] (DM_TARGET_MSG): Likewise. [!DM_DEV_SET_GEOMETRY] (DM_DEV_SET_GEOMETRY): Likewise.

---
 dm.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
dm.c +13 -0
index 79bb7c7..66b615d 100644
@@ -7,6 +7,19 @@
 
 # if DM_VERSION_MAJOR == 4
 
+/* Definitions for command which have been added later */
+
+#  ifndef DM_LIST_VERSIONS
+#   define DM_LIST_VERSIONS    _IOWR(DM_IOCTL, 0xd, struct dm_ioctl)
+#  endif
+#  ifndef DM_TARGET_MSG
+#   define DM_TARGET_MSG       _IOWR(DM_IOCTL, 0xe, struct dm_ioctl)
+#  endif
+#  ifndef DM_DEV_SET_GEOMETRY
+#   define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, 0xf, struct dm_ioctl)
+#  endif
+
+
 static void
 dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc)
 {
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#21 lore raw

PATCH 8/21 dm: Use static constants for offset sizes

In reply to a message not in the archive

This may improve readability an leads to more compact code.

---
 dm.c |   58 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 31 insertions(+), 27 deletions(-)
dm.c +31 -27
index 66b615d..adfa97e 100644
@@ -102,12 +102,14 @@ static void
 dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
 			 const char *extra, uint32_t extra_size)
 {
+	static const uint32_t target_spec_size =
+		sizeof(struct dm_target_spec);
 	uint32_t i;
 	uint32_t offset = ioc->data_start;
 
 	for (i = 0; i < ioc->target_count; i++) {
-		if (offset + (uint32_t) sizeof(struct dm_target_spec) >= offset &&
-		    offset + (uint32_t) sizeof(struct dm_target_spec) < extra_size) {
+		if (offset + target_spec_size >= offset &&
+		    offset + target_spec_size < extra_size) {
 			uint32_t new_offset;
 			const struct dm_target_spec *s =
 				(const struct dm_target_spec *) (extra + offset);
@@ -121,16 +123,14 @@ dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
 					    QUOTE_0_TERMINATED);
 			tprints(", string=");
 			print_quoted_string((const char *) (s + 1), extra_size -
-					    (offset +
-					    sizeof(struct dm_target_spec)),
+					    (offset + target_spec_size),
 					    QUOTE_0_TERMINATED);
 			tprintf("}");
 			if (entering(tcp))
 				new_offset = offset + s->next;
 			else
 				new_offset = ioc->data_start + s->next;
-			if (new_offset <= offset +
-			    (uint32_t) sizeof(struct dm_target_spec))
+			if (new_offset <= offset + target_spec_size)
 				goto misplaced;
 			offset = new_offset;
 		} else {
@@ -145,13 +145,15 @@ static void
 dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra,
 			 uint32_t extra_size)
 {
+	static const uint32_t target_deps_dev_offs =
+		offsetof(struct dm_target_deps, dev);
 	uint32_t offset = ioc->data_start;
-	if (offset + (uint32_t) offsetof(struct dm_target_deps, dev) >= offset &&
-	    offset + (uint32_t) offsetof(struct dm_target_deps, dev) <= extra_size) {
 
+	if (offset + target_deps_dev_offs >= offset &&
+	    offset + target_deps_dev_offs <= extra_size) {
 		uint32_t i;
-		uint32_t space = (extra_size - (offset +
-			offsetof(struct dm_target_deps, dev))) / sizeof(__u64);
+		uint32_t space = (extra_size - offset - target_deps_dev_offs) /
+			sizeof(__u64);
 		const struct dm_target_deps *s =
 			(const struct dm_target_deps *) (extra + offset);
 
@@ -173,11 +175,13 @@ static void
 dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
 		       uint32_t extra_size)
 {
+	static const uint32_t name_list_name_offs =
+		offsetof(struct dm_name_list, name);
 	uint32_t offset = ioc->data_start;
 
 	while (1) {
-		if (offset + (uint32_t) offsetof(struct dm_name_list, name) >= offset &&
-		    offset + (uint32_t) offsetof(struct dm_name_list, name) < extra_size) {
+		if (offset + name_list_name_offs >= offset &&
+		    offset + name_list_name_offs < extra_size) {
 			const struct dm_name_list *s =
 				(const struct dm_name_list *) (extra + offset);
 
@@ -186,13 +190,12 @@ dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
 			tprintf(", {dev=makedev(%u, %u), name=", major(s->dev),
 				minor(s->dev));
 			print_quoted_string(s->name, extra_size - (offset +
-					    offsetof(struct dm_name_list,
-					    name)), QUOTE_0_TERMINATED);
+					    name_list_name_offs),
+					    QUOTE_0_TERMINATED);
 			tprints("}");
 			if (!s->next)
 				break;
-			if (offset + s->next <= offset +
-			    (uint32_t) offsetof(struct dm_name_list, name))
+			if (offset + s->next <= offset + name_list_name_offs)
 				goto misplaced;
 			offset = offset + s->next;
 		} else {
@@ -207,26 +210,25 @@ static void
 dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra,
 			     uint32_t extra_size)
 {
+	static const uint32_t target_vers_name_offs =
+		offsetof(struct dm_target_versions, name);
 	uint32_t offset = ioc->data_start;
 
 	while (1) {
-		if (offset + (uint32_t) offsetof(struct dm_target_versions, name) >=
-		    offset &&
-		    offset + (uint32_t) offsetof(struct dm_target_versions, name) <
-		    extra_size) {
+		if (offset + target_vers_name_offs >= offset &&
+		    offset + target_vers_name_offs < extra_size) {
 			const struct dm_target_versions *s =
 			    (const struct dm_target_versions *)(extra + offset);
 
 			tprints(", {name=");
 			print_quoted_string(s->name, extra_size - (offset +
-					    offsetof(struct dm_target_versions,
-					    name)), QUOTE_0_TERMINATED);
+					    target_vers_name_offs),
+					    QUOTE_0_TERMINATED);
 			tprintf(", version=%" PRIu32 ".%" PRIu32 ".%" PRIu32 "}",
 				s->version[0], s->version[1], s->version[2]);
 			if (!s->next)
 				break;
-			if (offset + s->next <= offset +
-			    (uint32_t) offsetof(struct dm_target_versions, name))
+			if (offset + s->next <= offset + target_vers_name_offs)
 				goto misplaced;
 			offset = offset + s->next;
 		} else {
@@ -242,17 +244,19 @@ static void
 dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
 			uint32_t extra_size)
 {
+	static const uint32_t target_msg_message_offs =
+		offsetof(struct dm_target_msg, message);
 	uint32_t offset = ioc->data_start;
 
-	if (offset + (uint32_t) offsetof(struct dm_target_msg, message) >= offset &&
-	    offset + (uint32_t) offsetof(struct dm_target_msg, message) < extra_size) {
+	if (offset + target_msg_message_offs >= offset &&
+	    offset + target_msg_message_offs < extra_size) {
 		const struct dm_target_msg *s =
 			(const struct dm_target_msg *) (extra + offset);
 
 		tprintf(", {sector=%" PRIu64 ", message=",
 			(uint64_t) s->sector);
 		print_quoted_string(s->message, extra_size -
-				    offsetof(struct dm_target_msg, message),
+				    target_msg_message_offs,
 				    QUOTE_0_TERMINATED);
 		tprints("}");
 	} else {
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#22 lore raw

PATCH 9/21 dm: Remove char * cast

In reply to a message not in the archive
---
 dm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
dm.c +1 -1
index adfa97e..3ee74c3 100644
@@ -286,7 +286,7 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	char *extra = NULL;
 	uint32_t extra_size = 0;
 
-	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *) &ioc) < 0)
+	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), &ioc) < 0)
 		return 0;
 	tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1],
 		ioc.version[2]);
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#23 lore raw

PATCH 10/21 dm: use => instead of , for splitting output structure from input

In reply to a message not in the archive
---
 dm.c             |    4 ++--
 tests/ioctl_dm.c |   12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)
dm.c +2 -2
index 3ee74c3..f23a65d 100644
@@ -288,8 +288,8 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 
 	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), &ioc) < 0)
 		return 0;
-	tprintf(", {version=%d.%d.%d", ioc.version[0], ioc.version[1],
-		ioc.version[2]);
+	tprintf("%s{version=%d.%d.%d",  entering(tcp) ? ", " : " => ",
+		ioc.version[0], ioc.version[1], ioc.version[2]);
 
 	/*
 	 * if we use a different version of ABI, do not attempt to decode
tests/ioctl_dm.c +6 -6
index ba484ee..3c43913 100644
@@ -42,7 +42,7 @@ main(void)
 	ioctl(-1, DM_VERSION, &s);
 	printf("ioctl(-1, DM_VERSION, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}, "
+	       "uuid=\"uuu\", flags=0} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
@@ -58,7 +58,7 @@ main(void)
 	printf("ioctl(-1, DM_TABLE_LOAD, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", target_count=1, flags=0, {sector_start=16, "
-	       "length=32, target_type=\"tgt\", string=\"tparams\"}}, "
+	       "length=32, target_type=\"tgt\", string=\"tparams\"}} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
@@ -69,7 +69,7 @@ main(void)
 	ioctl(-1, DM_TARGET_MSG, &s);
 	printf("ioctl(-1, DM_TARGET_MSG, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}}, "
+	       "uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
@@ -78,7 +78,7 @@ main(void)
 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
 	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0, string=\"10 20 30 40\"}, "
+	       "uuid=\"uuu\", flags=0, string=\"10 20 30 40\"} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
@@ -87,7 +87,7 @@ main(void)
 	ioctl(-1, DM_DEV_RENAME, &s);
 	printf("ioctl(-1, DM_DEV_RENAME, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"}, "
+	       "uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
@@ -98,7 +98,7 @@ main(void)
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", target_count=4294967295, flags=0, "
 	       "{sector_start=0, length=0, target_type=\"\", string=\"\"}, "
-	       "/* misplaced struct dm_target_spec */ ...}, "
+	       "/* misplaced struct dm_target_spec */ ...} => "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#24 lore raw

PATCH 11/21 dm: Compare entering field values with exiting ones

In reply to a message not in the archive
---
 dm.c             |   74 ++++++++++++++++++++++++++++++++++++++++--------------
 tests/ioctl_dm.c |   26 +++++++------------
 2 files changed, 64 insertions(+), 36 deletions(-)
dm.c +55 -19
index f23a65d..b6fb11d 100644
@@ -282,28 +282,62 @@ dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
 static int
 dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
-	struct dm_ioctl ioc;
+	struct dm_ioctl *ioc;
+	struct dm_ioctl *entering_ioc = NULL;
+	bool ioc_changed = false;
 	char *extra = NULL;
 	uint32_t extra_size = 0;
 
-	if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), &ioc) < 0)
+	ioc = malloc(sizeof(* ioc));
+	if (!ioc)
 		return 0;
+
+	if (umoven(tcp, arg, sizeof(*ioc) - sizeof(ioc->data), ioc) < 0) {
+		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) {
+		free(ioc);
+		return 1;
+	}
+
 	tprintf("%s{version=%d.%d.%d",  entering(tcp) ? ", " : " => ",
-		ioc.version[0], ioc.version[1], ioc.version[2]);
+		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) {
+	if (ioc->version[0] != DM_VERSION_MAJOR) {
 		tprints(", /* Unsupported device mapper ABI version */ ...");
 		goto skip;
 	}
 
-	if (ioc.data_size > sizeof(ioc)) {
-		extra = malloc(ioc.data_size);
+	if (ioc->data_size > sizeof(ioc)) {
+		extra = malloc(ioc->data_size);
 		if (extra) {
-			extra_size = ioc.data_size;
+			extra_size = ioc->data_size;
 			if (umoven(tcp, arg, extra_size, extra) < 0) {
 				free(extra);
 				extra = NULL;
@@ -311,9 +345,9 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 			}
 		}
 	}
-	dm_decode_device(code, &ioc);
-	dm_decode_values(tcp, code, &ioc);
-	dm_decode_flags(&ioc);
+	dm_decode_device(code, ioc);
+	dm_decode_values(tcp, code, ioc);
+	dm_decode_flags(ioc);
 	if (abbrev(tcp))
 		tprints(", ...");
 	else
@@ -322,42 +356,42 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		case DM_TABLE_STATUS:
 			if (entering(tcp) || syserror(tcp))
 				break;
-			dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size);
+			dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
 			break;
 		case DM_TABLE_LOAD:
 			if (!entering(tcp))
 				break;
-			dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size);
+			dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
 			break;
 		case DM_TABLE_DEPS:
 			if (entering(tcp) || syserror(tcp))
 				break;
-			dm_decode_dm_target_deps(&ioc, extra, extra_size);
+			dm_decode_dm_target_deps(ioc, extra, extra_size);
 			break;
 		case DM_LIST_DEVICES:
 			if (entering(tcp) || syserror(tcp))
 				break;
-			dm_decode_dm_name_list(&ioc, extra, extra_size);
+			dm_decode_dm_name_list(ioc, extra, extra_size);
 			break;
 		case DM_LIST_VERSIONS:
 			if (entering(tcp) || syserror(tcp))
 				break;
-			dm_decode_dm_target_versions(&ioc, extra, extra_size);
+			dm_decode_dm_target_versions(ioc, extra, extra_size);
 			break;
 		case DM_TARGET_MSG:
 			if (entering(tcp)) {
-				dm_decode_dm_target_msg(&ioc, extra,
+				dm_decode_dm_target_msg(ioc, extra,
 							extra_size);
 			} else if (!syserror(tcp) &&
-			    ioc.flags & DM_DATA_OUT_FLAG) {
-				dm_decode_string(&ioc, extra, extra_size);
+			    ioc->flags & DM_DATA_OUT_FLAG) {
+				dm_decode_string(ioc, extra, extra_size);
 			}
 			break;
 		case DM_DEV_RENAME:
 		case DM_DEV_SET_GEOMETRY:
 			if (!entering(tcp))
 				break;
-			dm_decode_string(&ioc, extra, extra_size);
+			dm_decode_string(ioc, extra, extra_size);
 			break;
 		}
 
@@ -365,6 +399,8 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	tprints("}");
 	if (extra)
 		free(extra);
+	if (exiting(tcp))
+		free(ioc);
 	return 1;
 }
 
tests/ioctl_dm.c +9 -17
index 3c43913..31f474c 100644
@@ -42,8 +42,6 @@ main(void)
 	ioctl(-1, DM_VERSION, &s);
 	printf("ioctl(-1, DM_VERSION, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
 
 	init_s();
@@ -58,9 +56,8 @@ main(void)
 	printf("ioctl(-1, DM_TABLE_LOAD, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", target_count=1, flags=0, {sector_start=16, "
-	       "length=32, target_type=\"tgt\", string=\"tparams\"}} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	       "length=32, target_type=\"tgt\", string=\"tparams\"}}) = "
+	       "-1 EBADF (%m)\n");
 
 	init_s();
 	s.u.tm.target_msg.sector = 0x1234;
@@ -69,27 +66,24 @@ main(void)
 	ioctl(-1, DM_TARGET_MSG, &s);
 	printf("ioctl(-1, DM_TARGET_MSG, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	       "uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}}) = "
+	       "-1 EBADF (%m)\n");
 
 	init_s();
 	strcpy(s.u.string, "10 20 30 40");
 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
 	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0, string=\"10 20 30 40\"} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	       "uuid=\"uuu\", flags=0, string=\"10 20 30 40\"}) = "
+	       "-1 EBADF (%m)\n");
 
 	init_s();
 	strcpy(s.u.string, "new-name");
 	ioctl(-1, DM_DEV_RENAME, &s);
 	printf("ioctl(-1, DM_DEV_RENAME, "
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	       "uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"}) = "
+	       "-1 EBADF (%m)\n");
 
 	init_s();
 	s.ioc.target_count = -1U;
@@ -98,9 +92,7 @@ main(void)
 	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
 	       "uuid=\"uuu\", target_count=4294967295, flags=0, "
 	       "{sector_start=0, length=0, target_type=\"\", string=\"\"}, "
-	       "/* misplaced struct dm_target_spec */ ...} => "
-	       "{version=4.1.2, dev=makedev(18, 52), name=\"nnn\", "
-	       "uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+	       "/* misplaced struct dm_target_spec */ ...}) = -1 EBADF (%m)\n");
 
 	puts("+++ exited with 0 +++");
 	return 0;
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#25 lore raw

PATCH 12/21 dm: Add inttypes.h, include reorder

In reply to a message not in the archive

Build failed otherwise on RHEL 5.

---
 dm.c             |    3 ++-
 tests/ioctl_dm.c |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)
dm.c +2 -1
index b6fb11d..a11196f 100644
@@ -2,8 +2,9 @@
 
 #ifdef HAVE_LINUX_DM_IOCTL_H
 
-# include <sys/ioctl.h>
+# include <inttypes.h>
 # include <linux/dm-ioctl.h>
+# include <sys/ioctl.h>
 
 # if DM_VERSION_MAJOR == 4
 
tests/ioctl_dm.c +1 -0
index 31f474c..94dbe93 100644
@@ -1,4 +1,5 @@
 #include "tests.h"
+#include <inttypes.h>
 #include <stdio.h>
 #include <stddef.h>
 #include <string.h>
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#26 lore raw

PATCH 13/21 dm: Move printing of dm_ioctl fields before allocation of extra data

In reply to a message not in the archive
---
 dm.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
dm.c +4 -3
index a11196f..73a9b57 100644
@@ -335,6 +335,10 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		goto skip;
 	}
 
+	dm_decode_device(code, ioc);
+	dm_decode_values(tcp, code, ioc);
+	dm_decode_flags(ioc);
+
 	if (ioc->data_size > sizeof(ioc)) {
 		extra = malloc(ioc->data_size);
 		if (extra) {
@@ -346,9 +350,6 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 			}
 		}
 	}
-	dm_decode_device(code, ioc);
-	dm_decode_values(tcp, code, ioc);
-	dm_decode_flags(ioc);
 	if (abbrev(tcp))
 		tprints(", ...");
 	else
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#27 lore raw

PATCH 14/21 dm: replace abbrev branching with goto

In reply to a message not in the archive
---
 dm.c |   78 ++++++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 40 insertions(+), 38 deletions(-)
dm.c +40 -38
index 73a9b57..814d7d2 100644
@@ -350,52 +350,54 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 			}
 		}
 	}
-	if (abbrev(tcp))
+
+	if (abbrev(tcp)) {
 		tprints(", ...");
-	else
-		switch (code) {
-		case DM_DEV_WAIT:
-		case DM_TABLE_STATUS:
-			if (entering(tcp) || syserror(tcp))
-				break;
-			dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
-			break;
-		case DM_TABLE_LOAD:
-			if (!entering(tcp))
-				break;
-			dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
+		goto skip;
+	}
+
+	switch (code) {
+	case DM_DEV_WAIT:
+	case DM_TABLE_STATUS:
+		if (entering(tcp) || syserror(tcp))
 			break;
-		case DM_TABLE_DEPS:
-			if (entering(tcp) || syserror(tcp))
-				break;
-			dm_decode_dm_target_deps(ioc, extra, extra_size);
+		dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
+		break;
+	case DM_TABLE_LOAD:
+		if (!entering(tcp))
 			break;
-		case DM_LIST_DEVICES:
-			if (entering(tcp) || syserror(tcp))
-				break;
-			dm_decode_dm_name_list(ioc, extra, extra_size);
+		dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
+		break;
+	case DM_TABLE_DEPS:
+		if (entering(tcp) || syserror(tcp))
 			break;
-		case DM_LIST_VERSIONS:
-			if (entering(tcp) || syserror(tcp))
-				break;
-			dm_decode_dm_target_versions(ioc, extra, extra_size);
+		dm_decode_dm_target_deps(ioc, extra, extra_size);
+		break;
+	case DM_LIST_DEVICES:
+		if (entering(tcp) || syserror(tcp))
 			break;
-		case DM_TARGET_MSG:
-			if (entering(tcp)) {
-				dm_decode_dm_target_msg(ioc, extra,
-							extra_size);
-			} else if (!syserror(tcp) &&
-			    ioc->flags & DM_DATA_OUT_FLAG) {
-				dm_decode_string(ioc, extra, extra_size);
-			}
+		dm_decode_dm_name_list(ioc, extra, extra_size);
+		break;
+	case DM_LIST_VERSIONS:
+		if (entering(tcp) || syserror(tcp))
 			break;
-		case DM_DEV_RENAME:
-		case DM_DEV_SET_GEOMETRY:
-			if (!entering(tcp))
-				break;
+		dm_decode_dm_target_versions(ioc, extra, extra_size);
+		break;
+	case DM_TARGET_MSG:
+		if (entering(tcp)) {
+			dm_decode_dm_target_msg(ioc, extra,
+						extra_size);
+		} else if (!syserror(tcp) && ioc->flags & DM_DATA_OUT_FLAG) {
 			dm_decode_string(ioc, extra, extra_size);
-			break;
 		}
+		break;
+	case DM_DEV_RENAME:
+	case DM_DEV_SET_GEOMETRY:
+		if (!entering(tcp))
+			break;
+		dm_decode_string(ioc, extra, extra_size);
+		break;
+	}
 
  skip:
 	tprints("}");
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#28 lore raw

PATCH 15/21 dm: Additional data_size/data_start checks

In reply to a message not in the archive
---
 dm.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
dm.c +7 -1
index 814d7d2..289bc0d 100644
@@ -293,7 +293,8 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	if (!ioc)
 		return 0;
 
-	if (umoven(tcp, arg, sizeof(*ioc) - sizeof(ioc->data), ioc) < 0) {
+	if ((umoven(tcp, arg, sizeof(*ioc) - sizeof(ioc->data), ioc) < 0) ||
+	    (ioc->data_size < offsetof(struct dm_ioctl, data_size))) {
 		free(ioc);
 		return 0;
 	}
@@ -335,6 +336,11 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		goto skip;
 	}
 
+	if (ioc->data_size < (sizeof(*ioc) - sizeof(ioc->data))) {
+		tprints(", /* Incorrect data_size */ ...");
+		goto skip;
+	}
+
 	dm_decode_device(code, ioc);
 	dm_decode_values(tcp, code, ioc);
 	dm_decode_flags(ioc);
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#29 lore raw

PATCH 16/21 dm: Add comment regarding intended fall-through in switch statement

In reply to a message not in the archive
---
 dm.c |    1 +
 1 file changed, 1 insertion(+)
dm.c +1 -0
index 289bc0d..5c908c9 100644
@@ -60,6 +60,7 @@ dm_decode_values(struct tcb *tcp, const unsigned int code,
 		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:
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#30 lore raw

PATCH 17/21 dm: Add data_size and data_offset fields to output

In reply to a message not in the archive
---
 dm.c             |    4 +++-
 tests/ioctl_dm.c |   41 ++++++++++++++++++++++++-----------------
 2 files changed, 27 insertions(+), 18 deletions(-)
dm.c +3 -1
index 5c908c9..caffc55 100644
@@ -327,7 +327,6 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 
 	tprintf("%s{version=%d.%d.%d",  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
@@ -337,6 +336,9 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		goto skip;
 	}
 
+	tprintf(", data_size=%u, data_start=%u",
+		ioc->data_size, ioc->data_start);
+
 	if (ioc->data_size < (sizeof(*ioc) - sizeof(ioc->data))) {
 		tprints(", /* Incorrect data_size */ ...");
 		goto skip;
tests/ioctl_dm.c +24 -17

76 lines not on this page · raw message

Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#31 lore raw

PATCH 18/21 tests/ioctl_dm: Allow passing size and data_start to init_s

In reply to a message not in the archive
---
 tests/ioctl_dm.c |   34 ++++++++++++++++------------------
 1 file changed, 16 insertions(+), 18 deletions(-)
tests/ioctl_dm.c +16 -18
index 6967ca2..c120ed2 100644
@@ -21,32 +21,30 @@ static struct s {
 	} u;
 } s;
 
-static void init_s(void)
+static void init_s(struct dm_ioctl *s, size_t size, size_t offs)
 {
-	memset(&s, 0, sizeof s);
-	s.ioc.version[0] = DM_VERSION_MAJOR;
-	s.ioc.version[1] = 1;
-	s.ioc.version[2] = 2;
-	s.ioc.data_size = sizeof(s);
-	s.ioc.data_start = offsetof(struct s, u);
-	s.ioc.dev = 0x1234;
-	strcpy(s.ioc.name, "nnn");
-	strcpy(s.ioc.uuid, "uuu");
+	memset(s, 0, size);
+	s->version[0] = DM_VERSION_MAJOR;
+	s->version[1] = 1;
+	s->version[2] = 2;
+	s->data_size = size;
+	s->data_start = offs;
+	s->dev = 0x1234;
+	strcpy(s->name, "nnn");
+	strcpy(s->uuid, "uuu");
 }
 
 int
 main(void)
 {
-	init_s();
-	s.ioc.data_size = sizeof(s.ioc);
-	s.ioc.data_start = 0;
+	init_s(&s.ioc, sizeof(s.ioc), 0);
 	ioctl(-1, DM_VERSION, &s);
 	printf("ioctl(-1, DM_VERSION, "
 	       "{version=4.1.2, data_size=%zu, data_start=0, "
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
 	       "-1 EBADF (%m)\n", sizeof(s.ioc));
 
-	init_s();
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.ioc.target_count = 1;
 	s.u.ts.target_spec.sector_start = 0x10;
 	s.u.ts.target_spec.length = 0x20;
@@ -62,7 +60,7 @@ main(void)
 	       "length=32, target_type=\"tgt\", string=\"tparams\"}}) = "
 	       "-1 EBADF (%m)\n", s.ioc.data_size, s.ioc.data_start);
 
-	init_s();
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.u.tm.target_msg.sector = 0x1234;
 	strcpy(s.u.string + offsetof(struct dm_target_msg, message),
 		"tmsg");
@@ -73,7 +71,7 @@ main(void)
 	       "{sector=4660, message=\"tmsg\"}}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
-	init_s();
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	strcpy(s.u.string, "10 20 30 40");
 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
 	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
@@ -82,7 +80,7 @@ main(void)
 	       "string=\"10 20 30 40\"}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
-	init_s();
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	strcpy(s.u.string, "new-name");
 	ioctl(-1, DM_DEV_RENAME, &s);
 	printf("ioctl(-1, DM_DEV_RENAME, "
@@ -91,7 +89,7 @@ main(void)
 	       "flags=0, string=\"new-name\"}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
-	init_s();
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.ioc.target_count = -1U;
 	ioctl(-1, DM_TABLE_LOAD, &s);
 	printf("ioctl(-1, DM_TABLE_LOAD, "
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#32 lore raw

PATCH 19/21 dm: Add check whether command uses parameters

In reply to a message not in the archive
---
 dm.c             |   25 ++++++++++++++++++++++---
 tests/ioctl_dm.c |    2 +-
 2 files changed, 23 insertions(+), 4 deletions(-)
dm.c +22 -3
index caffc55..a48aa72 100644
@@ -281,6 +281,23 @@ dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
 	}
 }
 
+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:
+		return false;
+	}
+
+	return true;
+}
+
 static int
 dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
@@ -336,8 +353,10 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		goto skip;
 	}
 
-	tprintf(", data_size=%u, data_start=%u",
-		ioc->data_size, ioc->data_start);
+	tprintf(", data_size=%u", ioc->data_size);
+
+	if (dm_ioctl_has_params(code))
+		tprintf(", data_start=%u", ioc->data_start);
 
 	if (ioc->data_size < (sizeof(*ioc) - sizeof(ioc->data))) {
 		tprints(", /* Incorrect data_size */ ...");
@@ -348,7 +367,7 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	dm_decode_values(tcp, code, ioc);
 	dm_decode_flags(ioc);
 
-	if (ioc->data_size > sizeof(ioc)) {
+	if (dm_ioctl_has_params(code) && (ioc->data_size > sizeof(ioc))) {
 		extra = malloc(ioc->data_size);
 		if (extra) {
 			extra_size = ioc->data_size;
tests/ioctl_dm.c +1 -1
index c120ed2..6ad4ea9 100644
@@ -40,7 +40,7 @@ main(void)
 	init_s(&s.ioc, sizeof(s.ioc), 0);
 	ioctl(-1, DM_VERSION, &s);
 	printf("ioctl(-1, DM_VERSION, "
-	       "{version=4.1.2, data_size=%zu, data_start=0, "
+	       "{version=4.1.2, data_size=%zu, "
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
 	       "-1 EBADF (%m)\n", sizeof(s.ioc));
 
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#33 lore raw

PATCH 20/21 dm: Fix printing of version field

In reply to a message not in the archive
---
 dm.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
dm.c +5 -1
index a48aa72..ff9e8ad 100644
@@ -342,7 +342,11 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 		return 1;
 	}
 
-	tprintf("%s{version=%d.%d.%d",  entering(tcp) ? ", " : " => ",
+	/*
+	 * 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
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#34 lore raw

PATCH 21/21 dm: rewrite structure decoding

In reply to a message not in the archive

Rewrite structure decoding in attempt to make it more in line with how structures and arrays are decoded in strace.
* Replace single structure retrieval with on-demand retrieval. It allows limiting amount of memory being allocated (suppose ioctl with data_size = -1)
* Check for abbrev in structure decoders itself. It allows distinguishing cases when we want to decode some additional data from cases when we are not.

---
 dm.c |  363 +++++++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 217 insertions(+), 146 deletions(-)
dm.c +217 -146
index ff9e8ad..d846233 100644
@@ -101,165 +101,254 @@ dm_decode_flags(const struct dm_ioctl *ioc)
 }
 
 static void
-dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
-			 const char *extra, uint32_t extra_size)
+dm_decode_dm_target_spec(struct tcb *tcp, unsigned long addr,
+			 const struct dm_ioctl *ioc)
 {
 	static const uint32_t target_spec_size =
 		sizeof(struct dm_target_spec);
 	uint32_t i;
 	uint32_t offset = ioc->data_start;
 
+	if (abbrev(tcp)) {
+		if (ioc->target_count)
+			tprints(", ...");
+
+		return;
+	}
+
 	for (i = 0; i < ioc->target_count; i++) {
-		if (offset + target_spec_size >= offset &&
-		    offset + target_spec_size < extra_size) {
-			uint32_t new_offset;
-			const struct dm_target_spec *s =
-				(const struct dm_target_spec *) (extra + offset);
-			tprintf(", {sector_start=%" PRIu64 ", length=%" PRIu64,
-				(uint64_t) s->sector_start,
-				(uint64_t) s->length);
-			if (!entering(tcp))
-				tprintf(", status=%" PRId32, s->status);
-			tprints(", target_type=");
-			print_quoted_string(s->target_type, DM_MAX_TYPE_NAME,
-					    QUOTE_0_TERMINATED);
-			tprints(", string=");
-			print_quoted_string((const char *) (s + 1), extra_size -
-					    (offset + target_spec_size),
-					    QUOTE_0_TERMINATED);
-			tprintf("}");
-			if (entering(tcp))
-				new_offset = offset + s->next;
-			else
-				new_offset = ioc->data_start + s->next;
-			if (new_offset <= offset + target_spec_size)
-				goto misplaced;
-			offset = new_offset;
-		} else {
-misplaced:
-			tprints(", /* misplaced struct dm_target_spec */ ...");
+		struct dm_target_spec s;
+		uint32_t new_offset;
+
+		if ((offset + target_spec_size) <= offset ||
+		    (offset + target_spec_size) > ioc->data_size)
+			goto misplaced;
+
+		tprints(", ");
+
+		if (i >= max_strlen) {
+			tprints("...");
 			break;
 		}
+
+		if (umove_or_printaddr(tcp, addr + offset, &s))
+			break;
+
+		tprintf("{sector_start=%" PRI__u64 ", length=%" PRI__u64,
+			s.sector_start, s.length);
+
+		if (!entering(tcp))
+			tprintf(", status=%" PRId32, s.status);
+
+		tprints(", target_type=");
+		print_quoted_string(s.target_type, DM_MAX_TYPE_NAME,
+				    QUOTE_0_TERMINATED);
+
+		tprints(", string=");
+		printstr_ex(tcp, addr + offset + target_spec_size,
+			     ioc->data_size - (offset + target_spec_size),
+			     QUOTE_0_TERMINATED);
+		tprintf("}");
+
+		if (entering(tcp))
+			new_offset = offset + s.next;
+		else
+			new_offset = ioc->data_start + s.next;
+
+		if (new_offset <= offset + target_spec_size)
+			goto misplaced;
+
+		offset = new_offset;
 	}
+
+	return;
+
+misplaced:
+	tprints(", /* misplaced struct dm_target_spec */ ...");
+}
+
+bool
+dm_print_dev(struct tcb *tcp, void *dev_ptr, size_t dev_size, void *dummy)
+{
+	uint64_t *dev = (uint64_t *) dev_ptr;
+
+	tprintf("makedev(%u, %u)", major(*dev), minor(*dev));
+
+	return 1;
 }
 
 static void
-dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra,
-			 uint32_t extra_size)
+dm_decode_dm_target_deps(struct tcb *tcp, unsigned long addr,
+			 const struct dm_ioctl *ioc)
 {
 	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 space;
 
-	if (offset + target_deps_dev_offs >= offset &&
-	    offset + target_deps_dev_offs <= extra_size) {
-		uint32_t i;
-		uint32_t space = (extra_size - offset - target_deps_dev_offs) /
-			sizeof(__u64);
-		const struct dm_target_deps *s =
-			(const struct dm_target_deps *) (extra + offset);
-
-		if (s->count > space)
-			goto misplaced;
-		tprints(", deps={");
-		for (i = 0; i < s->count; i++) {
-			tprintf("%smakedev(%u, %u)", i ? ", " : "",
-				major(s->dev[i]), minor(s->dev[i]));
-		}
-		tprints("}");
-	} else {
- misplaced:
-		tprints(", /* misplaced struct dm_target_deps */ ...");
+	if (abbrev(tcp)) {
+		tprints(", ...");
+		return;
 	}
+
+	tprints(", ");
+
+	if (offset + target_deps_dev_offs <= offset ||
+	    offset + target_deps_dev_offs > ioc->data_size)
+		goto misplaced;
+
+	if (umove_or_printaddr(tcp, addr + offset, &s))
+		return;
+
+	space = (ioc->data_size - offset - target_deps_dev_offs) / sizeof(__u64);
+
+	if (s.count > space)
+		goto misplaced;
+
+	tprintf("{count=%u, deps=", s.count);
+
+	print_array(tcp, addr + offset + target_deps_dev_offs, s.count,
+		    &dev_buf, sizeof(dev_buf), umoven_or_printaddr,
+		    dm_print_dev, NULL);
+
+	tprints("}");
+
+	return;
+
+misplaced:
+	tprints("/* misplaced struct dm_target_deps */ ...");
 }
 
 static void
-dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
-		       uint32_t extra_size)
+dm_decode_dm_name_list(struct tcb *tcp, unsigned long addr,
+		       const struct dm_ioctl *ioc)
 {
 	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;
+	uint32_t count;
 
-	while (1) {
-		if (offset + name_list_name_offs >= offset &&
-		    offset + name_list_name_offs < extra_size) {
-			const struct dm_name_list *s =
-				(const struct dm_name_list *) (extra + offset);
+	if (abbrev(tcp)) {
+		tprints(", ...");
+		return;
+	}
 
-			if (!s->dev)
-				break;
-			tprintf(", {dev=makedev(%u, %u), name=", major(s->dev),
-				minor(s->dev));
-			print_quoted_string(s->name, extra_size - (offset +
-					    name_list_name_offs),
-					    QUOTE_0_TERMINATED);
-			tprints("}");
-			if (!s->next)
-				break;
-			if (offset + s->next <= offset + name_list_name_offs)
-				goto misplaced;
-			offset = offset + s->next;
-		} else {
- misplaced:
-			tprints(", /* misplaced struct dm_name_list */ ...");
+	for (count = 0;; count++) {
+		if (offset + name_list_name_offs <= offset ||
+		    offset + name_list_name_offs > ioc->data_size)
+			goto misplaced;
+
+		tprints(", ");
+
+		if (count >= max_strlen) {
+			tprints("...");
+			break;
+		}
+
+		if (umove_or_printaddr(tcp, addr + offset, &s))
+			break;
+		if (!count && !s.dev) {
+			tprints("/* no devices present */");
 			break;
 		}
+
+		tprintf("{dev=makedev(%u, %u), name=", major(s.dev),
+			minor(s.dev));
+		printstr_ex(tcp, addr + offset + name_list_name_offs,
+			    ioc->data_size - (offset + name_list_name_offs),
+			    QUOTE_0_TERMINATED);
+		tprints("}");
+
+		if (!s.next)
+			break;
+		if (offset + s.next <= offset + name_list_name_offs)
+			goto misplaced;
+		offset = offset + s.next;
 	}
+
+	return;
+
+misplaced:
+	tprints(", /* misplaced struct dm_name_list */ ...");
 }
 
 static void
-dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra,
-			     uint32_t extra_size)
+dm_decode_dm_target_versions(struct tcb *tcp, unsigned long addr,
+			     const struct dm_ioctl *ioc)
 {
 	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;
+	uint32_t count;
 
-	while (1) {
-		if (offset + target_vers_name_offs >= offset &&
-		    offset + target_vers_name_offs < extra_size) {
-			const struct dm_target_versions *s =
-			    (const struct dm_target_versions *)(extra + offset);
+	if (abbrev(tcp)) {
+		tprints(", ...");
+		return;
+	}
 
-			tprints(", {name=");
-			print_quoted_string(s->name, extra_size - (offset +
-					    target_vers_name_offs),
-					    QUOTE_0_TERMINATED);
-			tprintf(", version=%" PRIu32 ".%" PRIu32 ".%" PRIu32 "}",
-				s->version[0], s->version[1], s->version[2]);
-			if (!s->next)
-				break;
-			if (offset + s->next <= offset + target_vers_name_offs)
-				goto misplaced;
-			offset = offset + s->next;
-		} else {
- misplaced:
-			tprints(", /* misplaced struct dm_target_versions */ "
-				"...");
+	for (count = 0;; count++) {
+		if (offset + target_vers_name_offs <= offset ||
+		    offset + target_vers_name_offs > ioc->data_size)
+			goto misplaced;
+
+		tprints(", ");
+
+		if (count >= max_strlen) {
+			tprints("...");
 			break;
 		}
+
+		if (umove_or_printaddr(tcp, addr + offset, &s))
+			break;
+
+		tprints("{name=");
+		printstr_ex(tcp, addr + offset + target_vers_name_offs,
+			    ioc->data_size - (offset + target_vers_name_offs),
+			    QUOTE_0_TERMINATED);
+		tprintf(", version=%" PRIu32 ".%" PRIu32 ".%" PRIu32 "}",
+			s.version[0], s.version[1], s.version[2]);
+
+		if (!s.next)
+			break;
+		if (offset + s.next <= offset + target_vers_name_offs)
+			goto misplaced;
+		offset = offset + s.next;
 	}
+
+	return;
+
+misplaced:
+	tprints(", /* misplaced struct dm_target_versions */ ...");
 }
 
 static void
-dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
-			uint32_t extra_size)
+dm_decode_dm_target_msg(struct tcb *tcp, unsigned long addr,
+		        const struct dm_ioctl *ioc)
 {
 	static const uint32_t target_msg_message_offs =
 		offsetof(struct dm_target_msg, message);
 	uint32_t offset = ioc->data_start;
 
-	if (offset + target_msg_message_offs >= offset &&
-	    offset + target_msg_message_offs < extra_size) {
-		const struct dm_target_msg *s =
-			(const struct dm_target_msg *) (extra + offset);
+	if (abbrev(tcp)) {
+		tprints(", ...");
+		return;
+	}
+
+	if (offset + target_msg_message_offs > offset &&
+	    offset + target_msg_message_offs <= ioc->data_size) {
+		struct dm_target_msg s;
 
-		tprintf(", {sector=%" PRIu64 ", message=",
-			(uint64_t) s->sector);
-		print_quoted_string(s->message, extra_size -
-				    target_msg_message_offs,
-				    QUOTE_0_TERMINATED);
+		if (umove_or_printaddr(tcp, addr + offset, &s))
+			return;
+
+		tprintf(", {sector=%" PRI__u64 ", message=", s.sector);
+		printstr_ex(tcp, addr + offset + target_msg_message_offs,
+			    ioc->data_size - offset - target_msg_message_offs,
+			    QUOTE_0_TERMINATED);
 		tprints("}");
 	} else {
 		tprints(", /* misplaced struct dm_target_msg */");
@@ -267,15 +356,20 @@ dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
 }
 
 static void
-dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
-		 uint32_t extra_size)
+dm_decode_string(struct tcb *tcp, unsigned long addr,
+		 const struct dm_ioctl *ioc)
 {
 	uint32_t offset = ioc->data_start;
 
-	if (offset < extra_size) {
+	if (abbrev(tcp)) {
+		tprints(", ...");
+		return;
+	}
+
+	if (offset < ioc->data_size) {
 		tprints(", string=");
-		print_quoted_string(extra + offset, extra_size - offset,
-				    QUOTE_0_TERMINATED);
+		printstr_ex(tcp, addr + offset, ioc->data_size - offset,
+			    QUOTE_0_TERMINATED);
 	} else {
 		tprints(", /* misplaced string */");
 	}
@@ -301,11 +395,9 @@ dm_ioctl_has_params(const unsigned int code)
 static int
 dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
-	struct dm_ioctl *ioc;
+	struct dm_ioctl *ioc = NULL;
 	struct dm_ioctl *entering_ioc = NULL;
 	bool ioc_changed = false;
-	char *extra = NULL;
-	uint32_t extra_size = 0;
 
 	ioc = malloc(sizeof(* ioc));
 	if (!ioc)
@@ -371,70 +463,49 @@ dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 	dm_decode_values(tcp, code, ioc);
 	dm_decode_flags(ioc);
 
-	if (dm_ioctl_has_params(code) && (ioc->data_size > sizeof(ioc))) {
-		extra = malloc(ioc->data_size);
-		if (extra) {
-			extra_size = ioc->data_size;
-			if (umoven(tcp, arg, extra_size, extra) < 0) {
-				free(extra);
-				extra = NULL;
-				extra_size = 0;
-			}
-		}
-	}
-
-	if (abbrev(tcp)) {
-		tprints(", ...");
-		goto skip;
-	}
-
 	switch (code) {
 	case DM_DEV_WAIT:
 	case DM_TABLE_STATUS:
 		if (entering(tcp) || syserror(tcp))
 			break;
-		dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
+		dm_decode_dm_target_spec(tcp, arg, ioc);
 		break;
 	case DM_TABLE_LOAD:
 		if (!entering(tcp))
 			break;
-		dm_decode_dm_target_spec(tcp, ioc, extra, extra_size);
+		dm_decode_dm_target_spec(tcp, arg, ioc);
 		break;
 	case DM_TABLE_DEPS:
 		if (entering(tcp) || syserror(tcp))
 			break;
-		dm_decode_dm_target_deps(ioc, extra, extra_size);
+		dm_decode_dm_target_deps(tcp, arg, ioc);
 		break;
 	case DM_LIST_DEVICES:
 		if (entering(tcp) || syserror(tcp))
 			break;
-		dm_decode_dm_name_list(ioc, extra, extra_size);
+		dm_decode_dm_name_list(tcp, arg, ioc);
 		break;
 	case DM_LIST_VERSIONS:
 		if (entering(tcp) || syserror(tcp))
 			break;
-		dm_decode_dm_target_versions(ioc, extra, extra_size);
+		dm_decode_dm_target_versions(tcp, arg, ioc);
 		break;
 	case DM_TARGET_MSG:
-		if (entering(tcp)) {
-			dm_decode_dm_target_msg(ioc, extra,
-						extra_size);
-		} else if (!syserror(tcp) && ioc->flags & DM_DATA_OUT_FLAG) {
-			dm_decode_string(ioc, extra, extra_size);
-		}
+		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 (!entering(tcp))
 			break;
-		dm_decode_string(ioc, extra, extra_size);
+		dm_decode_string(tcp, arg, ioc);
 		break;
 	}
 
  skip:
 	tprints("}");
-	if (extra)
-		free(extra);
 	if (exiting(tcp))
 		free(ioc);
 	return 1;
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#35 lore raw
In reply to a message not in the archive
Quoted 27 lines · Masatake YAMATO

I tested the patch and it works fine.
Could you add following patch if you approve?

commit bae7528fa92283726caac1ec7a6c306274f8899d

Author: Masatake YAMATO <[email protected]>
Date:   Mon Aug 22 17:44:55 2016 +0900

dm-ioctl: add a lvm private flag

When I run "dmsetup ls" under dm-ioctl patched strace, "strange DM_???" are found in its output.

# ./strace -e ioctl dmsetup ls > /dev/null
ioctl(3, DM_VERSION, {version=4.0.0, flags=0x4 /* DM_??? */}, ... ioctl(3, DM_LIST_DEVICES, {version=4.0.0, flags=0x4 /* DM_??? */}, ...
...

Associated definion for DM_??? is in lvm2 source tree. This commit imports the definion to dm-ioctl list.

xlat/dm_flags.in +0 -0
index ab4285c..1e7132b 100644

xlat/dm_flags.in line 7

Quoted 7 lines
xlat/dm_flags.in +2 -0
@@ -1,5 +1,7 @@
 DM_READONLY_FLAG
 DM_SUSPEND_FLAG
+/* Defined in lvm2/libdm/ioctl/libdm-iface.c */
+DM_EXISTS_FLAG 0x00000004
 DM_PERSISTENT_DEV_FLAG
 DM_STATUS_TABLE_FLAG
 DM_ACTIVE_PRESENT_FLAG

OK. This is the patch with the flag DM_EXISTS_FLAG added.

 Makefile.am         |    1 
 configure.ac        |    1 
 defs.h              |    1 
 dm.c                |  356 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 ioctl.c             |    4 
 tests/Makefile.am   |    2 
 tests/ioctl_dm.c    |   78 +++++++++++
 tests/ioctl_dm.test |   12 +
 xlat/dm_flags.in    |   19 ++
 9 files changed, 474 insertions(+)
Makefile.am +1 -0
Index: strace/Makefile.am
===================================================================
@@ -97,6 +97,7 @@ strace_SOURCES =	\
 	desc.c		\
 	dirent.c	\
 	dirent64.c	\
+	dm.c		\
 	empty.h		\
 	epoll.c		\
 	evdev.c		\
configure.ac +1 -0
Index: strace/configure.ac
===================================================================
@@ -354,6 +354,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	elf.h
 	inttypes.h
 	linux/bsg.h
+	linux/dm-ioctl.h
 	linux/dqblk_xfs.h
 	linux/falloc.h
 	linux/fiemap.h
defs.h +1 -0
Index: strace/defs.h
===================================================================
@@ -636,6 +636,7 @@ extern void print_struct_statfs64(struct
 
 extern void print_ifindex(unsigned int);
 
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
dm.c new file +356 -0

356 lines not on this page · raw message

ioctl.c +4 -0
Index: strace/ioctl.c
===================================================================
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
 	case 0x94:
 		return btrfs_ioctl(tcp, code, arg);
 #endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+	case 0xfd:
+		return dm_ioctl(tcp, code, arg);
+#endif
 	default:
 		break;
 	}
tests/Makefile.am +2 -0
Index: strace/tests/Makefile.am
===================================================================
@@ -162,6 +162,7 @@ check_PROGRAMS = \
 	inet-cmsg \
 	ioctl \
 	ioctl_block \
+	ioctl_dm \
 	ioctl_evdev \
 	ioctl_evdev-v \
 	ioctl_mtd \
@@ -507,6 +508,7 @@ DECODER_TESTS = \
 	inet-cmsg.test \
 	ioctl.test \
 	ioctl_block.test \
+	ioctl_dm.test \
 	ioctl_evdev.test \
 	ioctl_evdev-v.test \
 	ioctl_mtd.test \
tests/ioctl_dm.c new file +78 -0

78 lines not on this page · raw message

tests/ioctl_dm.test new file +12 -0
Index: strace/tests/ioctl_dm.test
===================================================================
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -veioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"
xlat/dm_flags.in new file +19 -0
Index: strace/xlat/dm_flags.in
===================================================================
@@ -0,0 +1,19 @@
+DM_READONLY_FLAG
+DM_SUSPEND_FLAG
+/* Defined in lvm2/libdm/ioctl/libdm-iface.c */
+DM_EXISTS_FLAG 0x00000004
+DM_PERSISTENT_DEV_FLAG
+DM_STATUS_TABLE_FLAG
+DM_ACTIVE_PRESENT_FLAG
+DM_INACTIVE_PRESENT_FLAG
+DM_BUFFER_FULL_FLAG
+DM_SKIP_BDGET_FLAG
+DM_SKIP_LOCKFS_FLAG
+DM_NOFLUSH_FLAG
+DM_QUERY_INACTIVE_TABLE_FLAG
+DM_UEVENT_GENERATED_FLAG
+DM_UUID_FLAG
+DM_SECURE_DATA_FLAG
+DM_DATA_OUT_FLAG
+DM_DEFERRED_REMOVE
+DM_INTERNAL_SUSPEND_FLAG

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot

#36 lore raw

cover Additional checks for strace DM ioctl decoder test

In reply to a message not in the archive

Hello.

Aside from additional checks themselves, this patchset also contains two notable changes:
* Fix for the previous patchset - misplaced comma printing ("dm: Fix comma printing for the case when dm_target_msg structure is inaccessible").
* Update of printstr_ex call, which enables proper handling of QUOTE_0_TERMINATED user style (it prints cropped string without ellipsis otherwise).

Eugene Syromyatnikov (9):
util: Add support for QUOTE_0_TERMINATED in user_style to
ptrintstr_ex
tests: Add check for printing of overlength strings to ioctl_dm test
tests: Add check for presence of HAVE_LINUX_DM_IOCTL_H macro
definition to ioctl_dm test
tests/ioctl_dm: whitespace
dm: Fix comma printing for the case when dm_target_msg structure is
inaccessible
tests/ioctl_dm: overly long string printing checks
tests: Some additional checks for ioctl_dm test
tests: Add ioctl_dm to .gitignore
tests: Add checks for abbreviated DM ioctl output

 dm.c                  |    4 +-
 tests/.gitignore      |    2 +
 tests/Makefile.am     |    2 +
 tests/ioctl_dm-v.c    |    2 +
 tests/ioctl_dm-v.test |   12 +
 tests/ioctl_dm.c      |  653 +++++++++++++++++++++++++++++++++++++++++++++++--
 tests/ioctl_dm.test   |    2 +-
 util.c                |   18 +-
 8 files changed, 674 insertions(+), 21 deletions(-)
 create mode 100644 tests/ioctl_dm-v.c
 create mode 100755 tests/ioctl_dm-v.test
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#37 lore raw

PATCH 1/1 device mapper ioctl

Quoted 9 lines · Eugene Syromyatnikov

Hello.

Aside from additional checks themselves, this patchset also contains two notable changes:
* Fix for the previous patchset - misplaced comma printing ("dm: Fix comma printing for the case when dm_target_msg structure is inaccessible").
* Update of printstr_ex call, which enables proper handling of QUOTE_0_TERMINATED user style (it prints cropped string without ellipsis otherwise).

Hi

Here I'm sending the device mapper ioctl patch with these changes merged.

In this piece of code:

+       dm_arg_open3->target3.next = 0xdeadbeef;
+       dm_arg_open3->param3[0] = '\1';
+       dm_arg_open3->param3[1] = '\2';
+       dm_arg_open3->param1[2] = '\0';

there should be "dm_arg_open3->param3[2]" instead of "dm_arg_open3->param1[2]". "dm_arg_open3->param1[2]" produces a warning about access beyond the end of array.

Mikulas

 Makefile.am           |    1 
 configure.ac          |    1 
 defs.h                |    1 
 dm.c                  |  552 ++++++++++++++++++++++++++++++++++++++
 ioctl.c               |    4 
 tests/.gitignore      |    2 
 tests/Makefile.am     |    4 
 tests/ioctl_dm-v.c    |    2 
 tests/ioctl_dm-v.test |   12 
 tests/ioctl_dm.c      |  726 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/ioctl_dm.test   |   12 
 util.c                |   18 +
 xlat/dm_flags.in      |   19 +
 13 files changed, 1351 insertions(+), 3 deletions(-)
Makefile.am +1 -0
Index: strace/Makefile.am
===================================================================
@@ -97,6 +97,7 @@ strace_SOURCES =	\
 	desc.c		\
 	dirent.c	\
 	dirent64.c	\
+	dm.c		\
 	empty.h		\
 	epoll.c		\
 	evdev.c		\
configure.ac +1 -0
Index: strace/configure.ac
===================================================================
@@ -354,6 +354,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	elf.h
 	inttypes.h
 	linux/bsg.h
+	linux/dm-ioctl.h
 	linux/dqblk_xfs.h
 	linux/falloc.h
 	linux/fiemap.h
defs.h +1 -0
Index: strace/defs.h
===================================================================
@@ -636,6 +636,7 @@ extern void print_struct_statfs64(struct
 
 extern void print_ifindex(unsigned int);
 
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
dm.c new file +552 -0

552 lines not on this page · raw message

ioctl.c +4 -0
Index: strace/ioctl.c
===================================================================
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
 	case 0x94:
 		return btrfs_ioctl(tcp, code, arg);
 #endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+	case 0xfd:
+		return dm_ioctl(tcp, code, arg);
+#endif
 	default:
 		break;
 	}
tests/Makefile.am +4 -0
Index: strace/tests/Makefile.am
===================================================================
@@ -162,6 +162,8 @@ check_PROGRAMS = \
 	inet-cmsg \
 	ioctl \
 	ioctl_block \
+	ioctl_dm \
+	ioctl_dm-v \
 	ioctl_evdev \
 	ioctl_evdev-v \
 	ioctl_mtd \
@@ -507,6 +509,8 @@ DECODER_TESTS = \
 	inet-cmsg.test \
 	ioctl.test \
 	ioctl_block.test \
+	ioctl_dm.test \
+	ioctl_dm-v.test \
 	ioctl_evdev.test \
 	ioctl_evdev-v.test \
 	ioctl_mtd.test \
tests/ioctl_dm.c new file +726 -0

726 lines not on this page · raw message

tests/ioctl_dm.test new file +12 -0
Index: strace/tests/ioctl_dm.test
===================================================================
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -s9 -eioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"
xlat/dm_flags.in new file +19 -0
Index: strace/xlat/dm_flags.in
===================================================================
@@ -0,0 +1,19 @@
+DM_READONLY_FLAG		(1 << 0)
+DM_SUSPEND_FLAG			(1 << 1)
+/* Defined in lvm2/libdm/ioctl/libdm-iface.c */
+DM_EXISTS_FLAG			(1 << 2)
+DM_PERSISTENT_DEV_FLAG		(1 << 3)
+DM_STATUS_TABLE_FLAG		(1 << 4)
+DM_ACTIVE_PRESENT_FLAG		(1 << 5)
+DM_INACTIVE_PRESENT_FLAG	(1 << 6)
+DM_BUFFER_FULL_FLAG		(1 << 8)
+DM_SKIP_BDGET_FLAG		(1 << 9)
+DM_SKIP_LOCKFS_FLAG		(1 << 10)
+DM_NOFLUSH_FLAG			(1 << 11)
+DM_QUERY_INACTIVE_TABLE_FLAG	(1 << 12)
+DM_UEVENT_GENERATED_FLAG	(1 << 13)
+DM_UUID_FLAG			(1 << 14)
+DM_SECURE_DATA_FLAG		(1 << 15)
+DM_DATA_OUT_FLAG		(1 << 16)
+DM_DEFERRED_REMOVE		(1 << 17)
+DM_INTERNAL_SUSPEND_FLAG	(1 << 18)
util.c +15 -3
Index: strace/util.c
===================================================================
@@ -820,13 +820,13 @@ printstr_ex(struct tcb *tcp, long addr,
 		outstr = xmalloc(outstr_size);
 	}
 
-	size = max_strlen;
+	size = max_strlen + 1;
 	if (len == -1) {
 		/*
 		 * Treat as a NUL-terminated string: fetch one byte more
 		 * because string_quote may look one byte ahead.
 		 */
-		if (umovestr(tcp, addr, size + 1, str) < 0) {
+		if (umovestr(tcp, addr, size, str) < 0) {
 			printaddr(addr);
 			return;
 		}
@@ -844,11 +844,23 @@ printstr_ex(struct tcb *tcp, long addr,
 
 	style |= user_style;
 
+	if (style & QUOTE_0_TERMINATED) {
+		if (size) {
+			--size;
+		} else {
+			tprints((len == -1) || (len == 0) ? "\"\"" : "\"\"...");
+			return;
+		}
+	}
+	if (size > max_strlen)
+		size = max_strlen;
+
 	/* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
 	 * or we were requested to print more than -s NUM chars)...
 	 */
 	ellipsis = (string_quote(str, outstr, size, style) &&
-			(len < 0 || (unsigned long) len > max_strlen));
+			((style & QUOTE_0_TERMINATED) ||
+				(unsigned long) len > max_strlen));
 
 	tprints(outstr);
 	if (ellipsis)
tests/.gitignore +2 -0
Index: strace/tests/.gitignore
===================================================================
@@ -103,6 +103,8 @@ getxxid
 inet-cmsg
 ioctl
 ioctl_block
+ioctl_dm
+ioctl_dm-v
 ioctl_evdev
 ioctl_evdev-v
 ioctl_mtd
tests/ioctl_dm-v.c new file +2 -0
Index: strace/tests/ioctl_dm-v.c
===================================================================
@@ -0,0 +1,2 @@
+#define VERBOSE 1
+#include "ioctl_dm.c"
tests/ioctl_dm-v.test new file +12 -0
Index: strace/tests/ioctl_dm-v.test
===================================================================
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check abbreviated decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -s9 -veioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot

A message that is not in the archive (sent off-list or not yet received): alpine.LRH.2.02.1610191626360.628-Hpncn10jQN4oNljnaZt3ZvA+iT7yCHsGwRM8/[email protected]

#39 lore raw

Re: [PATCH] device mapper ioctl

Quoted 4 lines · Mikulas Patocka

Hi

Here I'm sending the device mapper ioctl patch with these changes merged.

Hello.

Thank you for your contribution. The implementation of DM_* ioctl decoding is now in strace's master, you can check it out at
https://github.com/strace/strace/commit/a507a0bb777c552e43e1e45f302703a09ffea1b8

Could you please review it and let us know if there are any issues?

Quoted 8 lines

In this piece of code:

tests/ioctl_dm.c new file +4 -0
+       dm_arg_open3->target3.next = 0xdeadbeef;
+       dm_arg_open3->param3[0] = '\1';
+       dm_arg_open3->param3[1] = '\2';
+       dm_arg_open3->param1[2] = '\0';

there should be "dm_arg_open3->param3[2]" instead of "dm_arg_open3->param1[2]". "dm_arg_open3->param1[2]" produces a warning about access beyond the end of array.

Thank you for noticing, it was an oversight on my part.

Quoted 1 line

Mikulas

Signature · 10 lines
Eugene "eSyr" Syromyatnikov
mailto:[email protected]
xmpp:eSyr@jabber.{ru|org}

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

A message that is not in the archive (sent off-list or not yet received): CACGkJdts9AKHnXb+b6J2kfpDNZJZW12WaNaYukrA11PHtAydag-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#41 lore raw

Re: [PATCH] device mapper ioctl

Quoted 9 lines
Quoted 2 lines

Here I'm sending the device mapper ioctl patch with these changes merged.

Hello.

Thank you for your contribution. The implementation of DM_* ioctl decoding is now in strace's master, you can check it out at
https://github.com/strace/strace/commit/a507a0bb777c552e43e1e45f302703a09ffea1b8
Could you please review it and let us know if there are any issues?

It works fine on my Fedora 24(x86_64).
"make check" says "PASS" about ioctl_dm.test and ioctl_dm-v.test.

Very useful. Thank you.

Masatake YAMATO

Quoted 9 lines
Quoted 9 lines

In this piece of code:

tests/ioctl_dm.c new file +4 -0
+       dm_arg_open3->target3.next = 0xdeadbeef;
+       dm_arg_open3->param3[0] = '\1';
+       dm_arg_open3->param3[1] = '\2';
+       dm_arg_open3->param1[2] = '\0';

there should be "dm_arg_open3->param3[2]" instead of "dm_arg_open3->param1[2]". "dm_arg_open3->param1[2]" produces a warning about access beyond the end of array.

Quoted 9 lines

Thank you for noticing, it was an oversight on my part.

Quoted 1 line

Mikulas

Signature · 3 lines
Eugene "eSyr" Syromyatnikov
mailto:[email protected]
xmpp:eSyr@jabber.{ru|org}

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors Access to Intel Xeon Phi processor-based developer platforms. With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

#42 lore raw

PATCH 1/9 util: Add support for QUOTE_0_TERMINATED in user_style to ptrintstr_ex

In reply to a message not in the archive

This enables printing size-limited (expectedly) ASCIZ strings.

---
 util.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
util.c +15 -3
index 23a5fdb..00148d4 100644
@@ -820,13 +820,13 @@ printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
 		outstr = xmalloc(outstr_size);
 	}
 
-	size = max_strlen;
+	size = max_strlen + 1;
 	if (len == -1) {
 		/*
 		 * Treat as a NUL-terminated string: fetch one byte more
 		 * because string_quote may look one byte ahead.
 		 */
-		if (umovestr(tcp, addr, size + 1, str) < 0) {
+		if (umovestr(tcp, addr, size, str) < 0) {
 			printaddr(addr);
 			return;
 		}
@@ -844,11 +844,23 @@ printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
 
 	style |= user_style;
 
+	if (style & QUOTE_0_TERMINATED) {
+		if (size) {
+			--size;
+		} else {
+			tprints((len == -1) || (len == 0) ? "\"\"" : "\"\"...");
+			return;
+		}
+	}
+	if (size > max_strlen)
+		size = max_strlen;
+
 	/* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
 	 * or we were requested to print more than -s NUM chars)...
 	 */
 	ellipsis = (string_quote(str, outstr, size, style) &&
-			(len < 0 || (unsigned long) len > max_strlen));
+			((style & QUOTE_0_TERMINATED) ||
+				(unsigned long) len > max_strlen));
 
 	tprints(outstr);
 	if (ellipsis)
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#43 lore raw

PATCH 2/9 tests: Add check for printing of overlength strings to ioctl_dm test

In reply to a message not in the archive
---
 tests/ioctl_dm.c    |    2 +-
 tests/ioctl_dm.test |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
tests/ioctl_dm.c +1 -1
index 6ad4ea9..0a3bbf4 100644
@@ -77,7 +77,7 @@ main(void)
 	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
 	       "{version=4.1.2, data_size=%u, data_start=%u, "
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
-	       "string=\"10 20 30 40\"}) = -1 EBADF (%m)\n",
+	       "string=\"10 20 30 \"...}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
tests/ioctl_dm.test +1 -1
index db77616..78866d3 100755
@@ -5,7 +5,7 @@
 . "${srcdir=.}/init.sh"
 
 run_prog > /dev/null
-run_strace -a16 -veioctl $args > "$EXP"
+run_strace -a16 -s9 -veioctl $args > "$EXP"
 check_prog grep
 grep -v '^ioctl([012],' < "$LOG" > "$OUT"
 match_diff "$OUT" "$EXP"
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#44 lore raw

PATCH 3/9 tests: Add check for presence of HAVE_LINUX_DM_IOCTL_H macro definition to ioctl_dm test

In reply to a message not in the archive
---
 tests/ioctl_dm.c |   21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)
tests/ioctl_dm.c +15 -6
index 0a3bbf4..5f2689c 100644
@@ -1,10 +1,13 @@
 #include "tests.h"
-#include <inttypes.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <linux/dm-ioctl.h>
+
+#ifdef HAVE_LINUX_DM_IOCTL_H
+
+# include <inttypes.h>
+# include <stdio.h>
+# include <stddef.h>
+# include <string.h>
+# include <sys/ioctl.h>
+# include <linux/dm-ioctl.h>
 
 static struct s {
 	struct dm_ioctl ioc;
@@ -103,3 +106,9 @@ main(void)
 	puts("+++ exited with 0 +++");
 	return 0;
 }
+
+#else /* !HAVE_LINUX_DM_IOCTL_H */
+
+SKIP_MAIN_UNDEFINED("HAVE_LINUX_DM_IOCTL_H")
+
+#endif /* HAVE_LINUX_DM_IOCTL_H */
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#45 lore raw

PATCH 4/9 tests/ioctl_dm: whitespace

In reply to a message not in the archive
---
 tests/ioctl_dm.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
tests/ioctl_dm.c +2 -1
index 5f2689c..261983c 100644
@@ -24,7 +24,8 @@ static struct s {
 	} u;
 } s;
 
-static void init_s(struct dm_ioctl *s, size_t size, size_t offs)
+static void
+init_s(struct dm_ioctl *s, size_t size, size_t offs)
 {
 	memset(s, 0, size);
 	s->version[0] = DM_VERSION_MAJOR;
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#46 lore raw

PATCH 5/9 dm: Fix comma printing for the case when dm_target_msg structure is inaccessible

In reply to a message not in the archive
---
 dm.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
dm.c +3 -1
index d846233..b1d455c 100644
@@ -342,10 +342,12 @@ dm_decode_dm_target_msg(struct tcb *tcp, unsigned long addr,
 	    offset + target_msg_message_offs <= ioc->data_size) {
 		struct dm_target_msg s;
 
+		tprints(", ");
+
 		if (umove_or_printaddr(tcp, addr + offset, &s))
 			return;
 
-		tprintf(", {sector=%" PRI__u64 ", message=", s.sector);
+		tprintf("{sector=%" PRI__u64 ", message=", s.sector);
 		printstr_ex(tcp, addr + offset + target_msg_message_offs,
 			    ioc->data_size - offset - target_msg_message_offs,
 			    QUOTE_0_TERMINATED);
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#47 lore raw

PATCH 6/9 tests/ioctl_dm: overly long string printing checks

In reply to a message not in the archive
---
 tests/ioctl_dm.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
tests/ioctl_dm.c +4 -4
index 261983c..24232b7 100644
@@ -67,12 +67,12 @@ main(void)
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.u.tm.target_msg.sector = 0x1234;
 	strcpy(s.u.string + offsetof(struct dm_target_msg, message),
-		"tmsg");
+		"long target msg");
 	ioctl(-1, DM_TARGET_MSG, &s);
 	printf("ioctl(-1, DM_TARGET_MSG, "
 	       "{version=4.1.2, data_size=%u, data_start=%u, "
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
-	       "{sector=4660, message=\"tmsg\"}}) = -1 EBADF (%m)\n",
+	       "{sector=4660, message=\"long targ\"...}}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
@@ -85,12 +85,12 @@ main(void)
 	       s.ioc.data_size, s.ioc.data_start);
 
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
-	strcpy(s.u.string, "new-name");
+	strcpy(s.u.string, "new long name");
 	ioctl(-1, DM_DEV_RENAME, &s);
 	printf("ioctl(-1, DM_DEV_RENAME, "
 	       "{version=4.1.2, data_size=%u, data_start=%u, "
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
-	       "flags=0, string=\"new-name\"}) = -1 EBADF (%m)\n",
+	       "flags=0, string=\"new long \"...}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#48 lore raw

PATCH 7/9 tests: Some additional checks for ioctl_dm test

In reply to a message not in the archive
---
 tests/ioctl_dm.c |  505 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 505 insertions(+)
tests/ioctl_dm.c +505 -0
index 24232b7..0b2c5a7 100644
@@ -2,13 +2,26 @@
 
 #ifdef HAVE_LINUX_DM_IOCTL_H
 
+# include <errno.h>
 # include <inttypes.h>
+# include <stdbool.h>
 # include <stdio.h>
 # include <stddef.h>
 # include <string.h>
 # include <sys/ioctl.h>
 # include <linux/dm-ioctl.h>
 
+# define STR32 "AbCdEfGhIjKlMnOpQrStUvWxYz012345"
+
+static const char str129[] = STR32 STR32 STR32 STR32 "6";
+
+static const __u64 dts_sector_base = (__u64) 0xdeadca75facef157ULL;
+static const __u64 dts_sector_step = (__u64) 0x100000001ULL;
+static const __u64 dts_length_base = (__u64) 0xbadc0dedda7a1057ULL;
+static const __u64 dts_length_step = (__u64) 0x700000007ULL;
+static const __s32 dts_status_base = (__s32) 3141592653U;
+static const __s32 dts_status_step = 0x1234;
+
 static struct s {
 	struct dm_ioctl ioc;
 	union {
@@ -24,6 +37,43 @@ static struct s {
 	} u;
 } s;
 
+struct dm_table_open_test {
+	struct dm_ioctl ioc;
+	struct dm_target_spec target0;
+	char param0[1];
+	struct dm_target_spec target1;
+	char param1[2];
+	struct dm_target_spec target2;
+	char param2[3];
+	struct dm_target_spec target3;
+	char param3[4];
+	struct dm_target_spec target4;
+	char param4[5];
+	struct dm_target_spec target5;
+	char param5[6];
+	struct dm_target_spec target6;
+	char param6[7];
+	struct dm_target_spec target7;
+	char param7[8];
+	struct dm_target_spec target8;
+	char param8[9];
+	struct dm_target_spec target9;
+	char param9[10];
+};
+
+struct dm_target_msg_test {
+	struct dm_ioctl ioc;
+	struct dm_target_msg msg;
+};
+
+struct args {
+	unsigned int arg;
+	const char *str;
+	bool has_params;
+	bool has_event_nr;
+};
+
+
 static void
 init_s(struct dm_ioctl *s, size_t size, size_t offs)
 {
@@ -38,9 +88,147 @@ init_s(struct dm_ioctl *s, size_t size, size_t offs)
 	strcpy(s->uuid, "uuu");
 }
 
+static void
+init_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
+{
+	ptr->sector_start = dts_sector_base + dts_sector_step * id;
+	ptr->length       = dts_length_base + dts_length_step * id;
+	ptr->status       = dts_status_base + dts_status_step * id;
+
+	strncpy(ptr->target_type, str129 +
+		id % (sizeof(str129) - sizeof(ptr->target_type)),
+		id % (sizeof(ptr->target_type) + 1));
+	if (id % (sizeof(ptr->target_type) + 1) < sizeof(ptr->target_type))
+		ptr->target_type[id % (sizeof(ptr->target_type) + 1)] = '\0';
+}
+
+static void
+print_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
+{
+	printf("{sector_start=%" PRI__u64 ", length=%" PRI__u64 ", "
+	       "target_type=\"%.*s\", string=",
+	       dts_sector_base + dts_sector_step * id,
+	       dts_length_base + dts_length_step * id,
+	       (int) (id % (sizeof(ptr->target_type) + 1)),
+	       str129 + id % (sizeof(str129) - sizeof(ptr->target_type)));
+}
+
+# define ARG_STR(_arg) (_arg), #_arg
+
 int
 main(void)
 {
+	/* We can't check these properly for now */
+	static struct args dummy_check_cmds_nodev[] = {
+		{ ARG_STR(DM_REMOVE_ALL),    false },
+		{ ARG_STR(DM_LIST_DEVICES),  true  },
+		{ ARG_STR(DM_LIST_VERSIONS), true  },
+	};
+	static struct args dummy_check_cmds[] = {
+		{ ARG_STR(DM_DEV_CREATE),    false },
+		{ ARG_STR(DM_DEV_REMOVE),    false, true },
+		{ ARG_STR(DM_DEV_STATUS),    false },
+		{ ARG_STR(DM_DEV_WAIT),      true,  true },
+		{ ARG_STR(DM_TABLE_CLEAR),   false },
+		{ ARG_STR(DM_TABLE_DEPS),    true  },
+		{ ARG_STR(DM_TABLE_STATUS),  true  },
+	};
+
+	struct dm_ioctl *dm_arg =
+		tail_alloc(sizeof(*dm_arg) - sizeof(dm_arg->data));
+	struct dm_table_open_test *dm_arg_open1 =
+		tail_alloc(offsetof(struct dm_table_open_test, target1));
+	struct dm_table_open_test *dm_arg_open2 =
+		tail_alloc(offsetof(struct dm_table_open_test, param1));
+	struct dm_table_open_test *dm_arg_open3 =
+		tail_alloc(offsetof(struct dm_table_open_test, target9));
+	struct dm_target_msg_test *dm_arg_msg =
+		tail_alloc(sizeof(*dm_arg_msg));
+
+	int saved_errno;
+	unsigned int i;
+
+
+	/* Incorrect operation */
+	ioctl(-1, _IOW(DM_IOCTL, 0xde, int), dm_arg);
+	printf("ioctl(-1, _IOC(_IOC_WRITE, %#04x, 0xde, %#04zx), %p) = "
+	        "-1 EBADF (%m)\n",
+		DM_IOCTL, sizeof(int), dm_arg);
+
+
+	/* DM_VERSION */
+	/* Incorrect pointer */
+	ioctl(-1, DM_VERSION, dm_arg + 1);
+	printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", dm_arg + 1);
+
+	/* Incorrect data_size */
+	init_s(dm_arg, 0, 0);
+	ioctl(-1, DM_VERSION, &s);
+	printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", &s);
+
+	/* Incorrect version */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	dm_arg->version[0] = 0xbadc0ded;
+	dm_arg->version[1] = 0xbadc0dee;
+	dm_arg->version[2] = 0xbadc0def;
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, {version=%u.%u.%u, "
+	       "/* Unsupported device mapper ABI version */ ...}) = "
+	       "-1 EBADF (%m)\n", 0xbadc0ded, 0xbadc0dee, 0xbadc0def);
+
+	/* Incorrect data_size */
+	init_s(dm_arg, 14, 64);
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=14, "
+	       "/* Incorrect data_size */ ...}) = -1 EBADF (%m)\n");
+
+	/* Unterminated name/uuid */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	strncpy(dm_arg->name, str129, sizeof(dm_arg->name));
+	strncpy(dm_arg->uuid, str129, sizeof(dm_arg->uuid));
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=%zu, "
+	       "dev=makedev(18, 52), name=\"%.127s\", uuid=\"%.128s\", "
+	       "flags=0}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg) - sizeof(dm_arg->data), str129, str129);
+
+	/* Normal call */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, "
+	       "{version=4.1.2, data_size=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
+	       "-1 EBADF (%m)\n", sizeof(*dm_arg) - sizeof(dm_arg->data));
+
+	/* Zero dev, name, uuid */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	dm_arg->data_size = 0xfacefeed;
+	dm_arg->dev = 0;
+	dm_arg->name[0] = '\0';
+	dm_arg->uuid[0] = '\0';
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, "
+	       "{version=4.1.2, data_size=%u, flags=0}) = "
+	       "-1 EBADF (%m)\n", 0xfacefeed);
+
+	/* Flag */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	dm_arg->flags = 0xffffffff;
+	ioctl(-1, DM_VERSION, dm_arg);
+	printf("ioctl(-1, DM_VERSION, "
+	       "{version=4.1.2, data_size=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags="
+	       "DM_READONLY_FLAG|DM_SUSPEND_FLAG|DM_EXISTS_FLAG|"
+	       "DM_PERSISTENT_DEV_FLAG|DM_STATUS_TABLE_FLAG|"
+	       "DM_ACTIVE_PRESENT_FLAG|DM_INACTIVE_PRESENT_FLAG|"
+	       "DM_BUFFER_FULL_FLAG|DM_SKIP_BDGET_FLAG|DM_SKIP_LOCKFS_FLAG|"
+	       "DM_NOFLUSH_FLAG|DM_QUERY_INACTIVE_TABLE_FLAG|"
+	       "DM_UEVENT_GENERATED_FLAG|DM_UUID_FLAG|DM_SECURE_DATA_FLAG|"
+	       "DM_DATA_OUT_FLAG|DM_DEFERRED_REMOVE|DM_INTERNAL_SUSPEND_FLAG|"
+	       "0xfff80080}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg) - sizeof(dm_arg->data));
+
+	/* Normal call */
 	init_s(&s.ioc, sizeof(s.ioc), 0);
 	ioctl(-1, DM_VERSION, &s);
 	printf("ioctl(-1, DM_VERSION, "
@@ -48,6 +236,61 @@ main(void)
 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
 	       "-1 EBADF (%m)\n", sizeof(s.ioc));
 
+
+	/* DM_REMOVE_ALL */
+	/* DM_LIST_DEVICES */
+	/* DM_LIST_VERSIONS */
+	for (i = 0; i < ARRAY_SIZE(dummy_check_cmds_nodev); i++) {
+		init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+		ioctl(-1, dummy_check_cmds_nodev[i].arg, dm_arg);
+		printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
+		       "flags=0}) = -1 EBADF (%m)\n",
+		       dummy_check_cmds_nodev[i].str,
+		       sizeof(*dm_arg) - sizeof(dm_arg->data),
+		       dummy_check_cmds_nodev[i].has_params ?
+		       ", data_start=0" : "");
+	}
+
+
+	/* DM_DEV_CREATE */
+	/* DM_DEV_REMOVE */
+	/* DM_DEV_STATUS */
+	/* DM_DEV_WAIT */
+	/* DM_TABLE_CLEAR */
+	/* DM_TABLE_DEPS */
+	/* DM_TABLE_STATUS */
+	for (i = 0; i < ARRAY_SIZE(dummy_check_cmds); i++) {
+		init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+		ioctl(-1, dummy_check_cmds[i].arg, dm_arg);
+		printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
+		       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\"%s, "
+		       "flags=0}) = -1 EBADF (%m)\n", dummy_check_cmds[i].str,
+		       sizeof(*dm_arg) - sizeof(dm_arg->data),
+		       dummy_check_cmds[i].has_params ? ", data_start=0" : "",
+		       dummy_check_cmds[i].has_event_nr ? ", event_nr=0" : "");
+	}
+
+
+	/* DM_DEV_SUSPEND */
+	init_s(&s.ioc, sizeof(s.ioc), 0);
+	s.ioc.flags = DM_SUSPEND_FLAG;
+	s.ioc.event_nr = 0xbadc0ded;
+	ioctl(-1, DM_DEV_SUSPEND, &s);
+	printf("ioctl(-1, DM_DEV_SUSPEND, "
+	       "{version=4.1.2, data_size=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "flags=DM_SUSPEND_FLAG}) = -1 EBADF (%m)\n", sizeof(s.ioc));
+
+	init_s(&s.ioc, sizeof(s.ioc), 0);
+	s.ioc.event_nr = 0xbadc0ded;
+	ioctl(-1, DM_DEV_SUSPEND, &s);
+	printf("ioctl(-1, DM_DEV_SUSPEND, "
+	       "{version=4.1.2, data_size=%zu, dev=makedev(18, 52), "
+	       "name=\"nnn\", uuid=\"uuu\", event_nr=3134983661, "
+	       "flags=0}) = -1 EBADF (%m)\n", sizeof(s.ioc));
+
+
+	/* DM_TABLE_LOAD */
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.ioc.target_count = 1;
 	s.u.ts.target_spec.sector_start = 0x10;
@@ -64,6 +307,164 @@ main(void)
 	       "length=32, target_type=\"tgt\", string=\"tparams\"}}) = "
 	       "-1 EBADF (%m)\n", s.ioc.data_size, s.ioc.data_start);
 
+	/* No targets */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data),
+		sizeof(*dm_arg) - sizeof(dm_arg->data));
+	dm_arg->data_size = sizeof(*dm_arg);
+	dm_arg->target_count = 0;
+	ioctl(-1, DM_TABLE_LOAD, dm_arg);
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=0, flags=0}) = -1 EBADF (%m)\n", sizeof(*dm_arg),
+	       sizeof(*dm_arg) - sizeof(dm_arg->data));
+
+	/* Invalid data_start */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0xfffffff8);
+	dm_arg->data_size = sizeof(*dm_arg);
+	dm_arg->target_count = 1234;
+	ioctl(-1, DM_TABLE_LOAD, dm_arg);
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%u, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=1234, flags=0, "
+	       "/* misplaced struct dm_target_spec */ ...}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg), 0xfffffff8);
+
+	/* Inaccessible pointer */
+	init_s(&dm_arg_open1->ioc, offsetof(struct dm_table_open_test, target1),
+	       offsetof(struct dm_table_open_test, target1));
+	dm_arg_open1->ioc.data_size = sizeof(*dm_arg_open1);
+	dm_arg_open1->ioc.target_count = 0xdeaddea1;
+	ioctl(-1, DM_TABLE_LOAD, dm_arg_open1);
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=3735936673, flags=0, %p}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg_open1),
+	       offsetof(struct dm_table_open_test, target1),
+	       (char *) dm_arg_open1 +
+	       offsetof(struct dm_table_open_test, target1));
+
+	/* Inaccessible string */
+	init_s(&dm_arg_open2->ioc, offsetof(struct dm_table_open_test, param1),
+	       offsetof(struct dm_table_open_test, target1));
+	dm_arg_open2->ioc.data_size = sizeof(*dm_arg_open2);
+	dm_arg_open2->ioc.target_count = 2;
+	init_dm_target_spec(&dm_arg_open2->target1, 7);
+	dm_arg_open2->target1.next =
+		offsetof(struct dm_table_open_test, target3) -
+		offsetof(struct dm_table_open_test, target1);
+	ioctl(-1, DM_TABLE_LOAD, dm_arg_open2);
+	saved_errno = errno;
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=2, flags=0, ",
+	       sizeof(*dm_arg_open2),
+	       offsetof(struct dm_table_open_test, target1));
+	print_dm_target_spec(&dm_arg_open2->target1, 7);
+	errno = saved_errno;
+	printf("%p}, %p}) = -1 EBADF (%m)\n",
+	       (char *) dm_arg_open2 +
+	       offsetof(struct dm_table_open_test, param1),
+	       (char *) dm_arg_open2 +
+	       offsetof(struct dm_table_open_test, target3));
+
+	/* Incorrect next */
+	init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target5),
+	       offsetof(struct dm_table_open_test, target0));
+	dm_arg_open3->ioc.target_count = 4;
+
+	init_dm_target_spec(&dm_arg_open3->target0, 9);
+	dm_arg_open3->target0.next =
+		offsetof(struct dm_table_open_test, target1) -
+		offsetof(struct dm_table_open_test, target0);
+	dm_arg_open3->param0[0] = '\0';
+
+	init_dm_target_spec(&dm_arg_open3->target1, 15);
+	dm_arg_open3->target1.next =
+		offsetof(struct dm_table_open_test, target3) -
+		offsetof(struct dm_table_open_test, target1);
+	dm_arg_open3->param1[0] = '\377';
+	dm_arg_open3->param1[1] = '\0';
+
+	init_dm_target_spec(&dm_arg_open3->target3, 42);
+	dm_arg_open3->target3.next = 0xdeadbeef;
+	dm_arg_open3->param3[0] = '\1';
+	dm_arg_open3->param3[1] = '\2';
+	dm_arg_open3->param1[2] = '\0';
+
+	ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
+	saved_errno = errno;
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=4, flags=0, ",
+	       offsetof(struct dm_table_open_test, target5),
+	       offsetof(struct dm_table_open_test, target0));
+	print_dm_target_spec(&dm_arg_open3->target0, 9);
+	printf("\"\"}, ");
+	print_dm_target_spec(&dm_arg_open3->target1, 15);
+	printf("\"\\377\"}, ");
+	print_dm_target_spec(&dm_arg_open3->target1, 42);
+	errno = saved_errno;
+	printf("\"\\1\\2\"}, /* misplaced struct dm_target_spec */ ...}) = "
+	       "-1 EBADF (%m)\n");
+
+	#define FILL_DM_TARGET(id, id_next) \
+		do { \
+			init_dm_target_spec(&dm_arg_open3->target##id, id); \
+			dm_arg_open3->target##id.next = \
+				offsetof(struct dm_table_open_test, \
+					target##id_next) - \
+				offsetof(struct dm_table_open_test, \
+					target##id); \
+			strncpy(dm_arg_open3->param##id, str129 + id * 2, id); \
+			dm_arg_open3->param##id[id] = '\0'; \
+		} while (0)
+	#define PRINT_DM_TARGET(id) \
+		do { \
+			print_dm_target_spec(&dm_arg_open3->target##id, id); \
+			printf("\"%.*s\"}, ", id, str129 + id * 2); \
+		} while (0)
+
+	/* max_strlen limit */
+	init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target9),
+	       offsetof(struct dm_table_open_test, target0));
+	dm_arg_open3->ioc.data_size = sizeof(*dm_arg_open3);
+	dm_arg_open3->ioc.target_count = 0xbadc0ded;
+	FILL_DM_TARGET(0, 1);
+	FILL_DM_TARGET(1, 2);
+	FILL_DM_TARGET(2, 3);
+	FILL_DM_TARGET(3, 4);
+	FILL_DM_TARGET(4, 5);
+	FILL_DM_TARGET(5, 6);
+	FILL_DM_TARGET(6, 7);
+	FILL_DM_TARGET(7, 8);
+	FILL_DM_TARGET(8, 9);
+	ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
+	saved_errno = errno;
+	printf("ioctl(-1, DM_TABLE_LOAD, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
+	       "target_count=3134983661, flags=0, ",
+	       sizeof(*dm_arg_open3),
+	       offsetof(struct dm_table_open_test, target0));
+	PRINT_DM_TARGET(0);
+	PRINT_DM_TARGET(1);
+	PRINT_DM_TARGET(2);
+	PRINT_DM_TARGET(3);
+	PRINT_DM_TARGET(4);
+	PRINT_DM_TARGET(5);
+	PRINT_DM_TARGET(6);
+	PRINT_DM_TARGET(7);
+	PRINT_DM_TARGET(8);
+	errno = saved_errno;
+	printf("...}) = -1 EBADF (%m)\n");
+
+
+	/* DM_TARGET_MSG */
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.u.tm.target_msg.sector = 0x1234;
 	strcpy(s.u.string + offsetof(struct dm_target_msg, message),
@@ -75,6 +476,71 @@ main(void)
 	       "{sector=4660, message=\"long targ\"...}}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
+	/* Invalid data_start */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data),
+		sizeof(*dm_arg) - sizeof(dm_arg->data));
+	dm_arg->data_size = sizeof(*dm_arg);
+	ioctl(-1, DM_TARGET_MSG, dm_arg);
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
+	       "/* misplaced struct dm_target_msg */}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg), sizeof(*dm_arg) - sizeof(dm_arg->data));
+
+	/* Invalid data_start */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0xffffffff);
+	dm_arg->data_size = sizeof(*dm_arg);
+	ioctl(-1, DM_TARGET_MSG, dm_arg);
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, data_size=%zu, data_start=%u, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
+	       "/* misplaced struct dm_target_msg */}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg), 0xffffffff);
+
+	/* Inaccessible pointer */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data), 0);
+	dm_arg->data_size = sizeof(*dm_arg) + sizeof(struct dm_target_msg);
+	dm_arg->data_start = sizeof(*dm_arg);
+	ioctl(-1, DM_TARGET_MSG, dm_arg);
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, %p}) "
+	       "= -1 EBADF (%m)\n",
+	       sizeof(*dm_arg) + sizeof(struct dm_target_msg),
+	       sizeof(*dm_arg), (char *) dm_arg + sizeof(*dm_arg));
+
+	/* Inaccessible string */
+	init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
+		offsetof(struct dm_target_msg_test, msg));
+	dm_arg_msg->ioc.data_size = sizeof(*dm_arg_msg) + 1;
+	dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
+	ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
+	       "{sector=%" PRI__u64 ", message=%p}}) "
+	       "= -1 EBADF (%m)\n",
+	       sizeof(*dm_arg_msg) + 1,
+	       offsetof(struct dm_target_msg_test, msg),
+	       (__u64) 0xdeadbeeffacef157ULL,
+	       (char *) dm_arg_msg +
+	       offsetof(struct dm_target_msg_test, msg.message));
+
+	/* Zero-sied string */
+	init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
+		offsetof(struct dm_target_msg_test, msg));
+	dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
+	ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
+	printf("ioctl(-1, DM_TARGET_MSG, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
+	       "{sector=%" PRI__u64 ", message=\"\"}}) "
+	       "= -1 EBADF (%m)\n",
+	       sizeof(*dm_arg_msg), offsetof(struct dm_target_msg_test, msg),
+	       (__u64) 0xdeadbeeffacef157ULL);
+
+
+	/* DM_DEV_SET_GEOMETRY */
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	strcpy(s.u.string, "10 20 30 40");
 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
@@ -84,6 +550,43 @@ main(void)
 	       "string=\"10 20 30 \"...}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
+
+	/* DM_DEV_RENAME */
+	/* Inaccessible data */
+	init_s(dm_arg, sizeof(*dm_arg) - sizeof(dm_arg->data),
+		sizeof(*dm_arg) - sizeof(dm_arg->data));
+	dm_arg->data_size = sizeof(*dm_arg);
+	ioctl(-1, DM_DEV_RENAME, dm_arg);
+	printf("ioctl(-1, DM_DEV_RENAME, "
+	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
+	       "flags=0, string=%p}) = -1 EBADF (%m)\n",
+	       sizeof(*dm_arg), sizeof(*dm_arg) - sizeof(dm_arg->data),
+	       (char *) dm_arg + sizeof(*dm_arg) - sizeof(dm_arg->data));
+
+	/* Incorrect data_start data */
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
+	s.ioc.data_start = 0xdeadbeef;
+	ioctl(-1, DM_DEV_RENAME, &s);
+	printf("ioctl(-1, DM_DEV_RENAME, "
+	       "{version=4.1.2, data_size=%u, data_start=3735928559, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
+	       "flags=0, /* misplaced string */}) = -1 EBADF (%m)\n",
+	       s.ioc.data_size);
+
+	/* Strange but still valid data_start */
+	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
+	/* Curiously, this is a valid structure */
+	s.ioc.data_start = offsetof(struct dm_ioctl, name) + 1;
+	ioctl(-1, DM_DEV_RENAME, &s);
+	printf("ioctl(-1, DM_DEV_RENAME, "
+	       "{version=4.1.2, data_size=%u, data_start=%zu, "
+	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
+	       "flags=0, string=\"nn\"}) = -1 EBADF (%m)\n",
+	       s.ioc.data_size,
+	       offsetof(struct dm_ioctl, name) + 1);
+
+	/* Correct data */
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	strcpy(s.u.string, "new long name");
 	ioctl(-1, DM_DEV_RENAME, &s);
@@ -93,6 +596,8 @@ main(void)
 	       "flags=0, string=\"new long \"...}) = -1 EBADF (%m)\n",
 	       s.ioc.data_size, s.ioc.data_start);
 
+
+	/* DM_TABLE_LOAD */
 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
 	s.ioc.target_count = -1U;
 	ioctl(-1, DM_TABLE_LOAD, &s);
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#49 lore raw

PATCH 8/9 tests: Add ioctl_dm to .gitignore

In reply to a message not in the archive
---
 tests/.gitignore |    1 +
 1 file changed, 1 insertion(+)
tests/.gitignore +1 -0
index a6d014d..9045117 100644
@@ -103,6 +103,7 @@ getxxid
 inet-cmsg
 ioctl
 ioctl_block
+ioctl_dm
 ioctl_evdev
 ioctl_evdev-v
 ioctl_mtd
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#50 lore raw

PATCH 9/9 tests: Add checks for abbreviated DM ioctl output

In reply to a message not in the archive
---
 tests/.gitignore      |    1 +
 tests/Makefile.am     |    2 +
 tests/ioctl_dm-v.c    |    2 +
 tests/ioctl_dm-v.test |   12 ++++
 tests/ioctl_dm.c      |  178 +++++++++++++++++++++++++++++++++++++++----------
 tests/ioctl_dm.test   |    2 +-
 6 files changed, 160 insertions(+), 37 deletions(-)
 create mode 100644 tests/ioctl_dm-v.c
 create mode 100755 tests/ioctl_dm-v.test
tests/.gitignore +1 -0
index 9045117..b2c5434 100644
@@ -104,6 +104,7 @@ inet-cmsg
 ioctl
 ioctl_block
 ioctl_dm
+ioctl_dm-v
 ioctl_evdev
 ioctl_evdev-v
 ioctl_mtd
tests/Makefile.am +2 -0
index 2405415..61b6db7 100644
@@ -164,6 +164,7 @@ check_PROGRAMS = \
 	ioctl \
 	ioctl_block \
 	ioctl_dm \
+	ioctl_dm-v \
 	ioctl_evdev \
 	ioctl_evdev-v \
 	ioctl_mtd \
@@ -513,6 +514,7 @@ DECODER_TESTS = \
 	ioctl.test \
 	ioctl_block.test \
 	ioctl_dm.test \
+	ioctl_dm-v.test \
 	ioctl_evdev.test \
 	ioctl_evdev-v.test \
 	ioctl_mtd.test \
tests/ioctl_dm-v.c new file +2 -0
new file mode 100644
index 0000000..d95058f
@@ -0,0 +1,2 @@
+#define VERBOSE 1
+#include "ioctl_dm.c"
tests/ioctl_dm-v.test new file +12 -0
new file mode 100755
index 0000000..4f6d64c
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check abbreviated decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -s9 -veioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"
tests/ioctl_dm.c +142 -36

332 lines not on this page · raw message

tests/ioctl_dm.test +1 -1
index 78866d3..6485205 100755
@@ -5,7 +5,7 @@
 . "${srcdir=.}/init.sh"
 
 run_prog > /dev/null
-run_strace -a16 -s9 -veioctl $args > "$EXP"
+run_strace -a16 -s9 -eioctl $args > "$EXP"
 check_prog grep
 grep -v '^ioctl([012],' < "$LOG" > "$OUT"
 match_diff "$OUT" "$EXP"
Signature · 6 lines
1.7.10.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
#51 lore raw
In reply to Mikulas Patocka

Hello.

While digging through your patch, looks like I've stumbled upon what looks like some minor out-of-bunds write in dm ioctl code: nl->dev = 0 write (drivers/md/dm-ioctl.c:533 @ b66484cd7) could be out of bounds in case userspace provided data_size of sizeof(struct dm_ioctl) and there are no device mapper devices present. Since data_size remains the same, this write does not make it to user space, and since this memory is kmalloc'ed, it's unlikely it overwrites any data since struct dm_ioctl size is not divisible by 32, but nevertheless.

Quoted 619 lines · Mikulas Patocka
Quoted 31 lines · Dmitry V. Levin

dm.c

Quoted 5 lines
dm.c new file +5 -0
+                   tprintf("}");
+                   if (entering(tcp))
+                           offset = offset + s->next;
+                   else
+                           offset = ioc->data_start + s->next;

This code trusts s->next; unfortunately, strace cannot trust syscall arguments, otherwise anything may happen, e.g.

$ cat ioctl_dm.c
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
int main(void)
{
      struct {
              struct dm_ioctl ioc;
              struct dm_target_spec spec;
              int i;
      } s = {
              .spec = { 0 },
              .ioc = {
                      .version[0] = DM_VERSION_MAJOR,
                      .data_size = sizeof(s),
                      .data_start = sizeof(s.ioc),
                      .target_count = -1U
              }
      };
      return !ioctl(-1, DM_TABLE_LOAD, &s);
}
$ strace -veioctl ./ioctl_dm
Quoted 7 lines

btw, this parser lacks tests. How one can easily verify that it works correctly? For example how a test for strace ioctl parser may look like see tests/ioctl_* files.

--
ldv

Here I'm sending new patch. It fixes the possible loop with s->next and adds tests:

 Makefile.am         |    1
 configure.ac        |    1
 defs.h              |    1
 dm.c                |  356 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 ioctl.c             |    4
 tests/Makefile.am   |    2
 tests/ioctl_dm.c    |   78 +++++++++++
 tests/ioctl_dm.test |   12 +
 xlat/dm_flags.in    |   17 ++
 9 files changed, 472 insertions(+)

Index: strace/Makefile.am
===================================================================

Makefile.am +1 -0
@@ -97,6 +97,7 @@ strace_SOURCES =      \
        desc.c          \
        dirent.c        \
        dirent64.c      \
+       dm.c            \
        empty.h         \
        epoll.c         \
        evdev.c         \

Index: strace/configure.ac
===================================================================

configure.ac +1 -0
@@ -354,6 +354,7 @@ AC_CHECK_HEADERS(m4_normalize([
        elf.h
        inttypes.h
        linux/bsg.h
+       linux/dm-ioctl.h
        linux/dqblk_xfs.h
        linux/falloc.h
        linux/fiemap.h

Index: strace/defs.h
===================================================================

defs.h +1 -0
@@ -640,6 +640,7 @@ extern void print_struct_statfs64(struct
 
 extern void print_ifindex(unsigned int);
 
+extern int dm_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);

Index: strace/dm.c
===================================================================

dm.c new file +356 -0
@@ -0,0 +1,356 @@
+#include "defs.h"
+
+#ifdef HAVE_LINUX_DM_IOCTL_H
+
+#include <sys/ioctl.h>
+#include <linux/dm-ioctl.h>
+
+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:
+               if (ioc->dev)
+                       tprintf(", dev=makedev(%u, %u)",
+                               major(ioc->dev), minor(ioc->dev));
+               if (ioc->name[0]) {
+                       tprints(", name=");
+                       print_quoted_string(ioc->name, DM_NAME_LEN,
+                                           QUOTE_0_TERMINATED);
+               }
+               if (ioc->uuid[0]) {
+                       tprints(", uuid=");
+                       print_quoted_string(ioc->uuid, DM_UUID_LEN,
+                                           QUOTE_0_TERMINATED);
+               }
+               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:
+                       tprintf(", target_count=%"PRIu32"",
+                               ioc->target_count);
+                       break;
+               case DM_DEV_SUSPEND:
+                       if (ioc->flags & DM_SUSPEND_FLAG)
+                               break;
+               case DM_DEV_RENAME:
+               case DM_DEV_REMOVE:
+               case DM_DEV_WAIT:
+                       tprintf(", event_nr=%"PRIu32"",
+                               ioc->event_nr);
+                       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:
+                       tprintf(", target_count=%"PRIu32"",
+                               ioc->target_count);
+                       tprintf(", open_count=%"PRIu32"",
+                               ioc->open_count);
+                       tprintf(", event_nr=%"PRIu32"",
+                               ioc->event_nr);
+                       break;
+               }
+       }
+}
+
+#include "xlat/dm_flags.h"
+
+static void
+dm_decode_flags(const struct dm_ioctl *ioc)
+{
+       tprints(", flags=");
+       printflags(dm_flags, ioc->flags, "DM_???");
+}
+
+static void
+dm_decode_dm_target_spec(struct tcb *tcp, const struct dm_ioctl *ioc,
+                        const char *extra, uint32_t extra_size)
+{
+       uint32_t i;
+       uint32_t offset = ioc->data_start;
+       for (i = 0; i < ioc->target_count; i++) {
+               if (offset + (uint32_t)sizeof(struct dm_target_spec) >= offset &&
+                   offset + (uint32_t)sizeof(struct dm_target_spec) < extra_size) {
+                       uint32_t new_offset;
+                       const struct dm_target_spec *s =
+                               (const struct dm_target_spec *)(extra + offset);
+                       tprintf(", {sector_start=%"PRIu64", length=%"PRIu64"",
+                               (uint64_t)s->sector_start, (uint64_t)s->length);
+                       if (!entering(tcp))
+                               tprintf(", status=%"PRId32"", s->status);
+                       tprints(", target_type=");
+                       print_quoted_string(s->target_type, DM_MAX_TYPE_NAME,
+                                           QUOTE_0_TERMINATED);
+                       tprints(", string=");
+                       print_quoted_string((const char *)(s + 1), extra_size -
+                                           (offset +
+                                           sizeof(struct dm_target_spec)),
+                                           QUOTE_0_TERMINATED);
+                       tprintf("}");
+                       if (entering(tcp))
+                               new_offset = offset + s->next;
+                       else
+                               new_offset = ioc->data_start + s->next;
+                       if (new_offset <= offset + (uint32_t)sizeof(struct dm_target_spec))
+                               goto misplaced;
+                       offset = new_offset;
+               } else {
+misplaced:
+                       tprints(", misplaced struct dm_target_spec");
+                       break;
+               }
+       }
+}
+
+static void
+dm_decode_dm_target_deps(const struct dm_ioctl *ioc, const char *extra,
+                        uint32_t extra_size)
+{
+       uint32_t offset = ioc->data_start;
+       if (offset + (uint32_t)offsetof(struct dm_target_deps, dev) >= offset &&
+           offset + (uint32_t)offsetof(struct dm_target_deps, dev) <= extra_size) {
+               uint32_t i;
+               uint32_t space = (extra_size - (offset +
+                       offsetof(struct dm_target_deps, dev))) / sizeof(__u64);
+               const struct dm_target_deps *s =
+                       (const struct dm_target_deps *)(extra + offset);
+               if (s->count > space)
+                       goto misplaced;
+               tprints(", deps={");
+               for (i = 0; i < s->count; i++) {
+                       tprintf("%smakedev(%u, %u)", i ? ", " : "",
+                               major(s->dev[i]), minor(s->dev[i]));
+               }
+               tprints("}");
+       } else {
+ misplaced:
+               tprints(", misplaced struct dm_target_deps");
+       }
+}
+
+static void
+dm_decode_dm_name_list(const struct dm_ioctl *ioc, const char *extra,
+                      uint32_t extra_size)
+{
+       uint32_t offset = ioc->data_start;
+       while (1) {
+               if (offset + (uint32_t)offsetof(struct dm_name_list, name) >= offset &&
+                   offset + (uint32_t)offsetof(struct dm_name_list, name) < extra_size) {
+                       const struct dm_name_list *s =
+                               (const struct dm_name_list *)(extra + offset);
+                       if (!s->dev)
+                               break;
+                       tprintf(", {dev=makedev(%u, %u), name=", major(s->dev), minor(s->dev));
+                       print_quoted_string(s->name, extra_size - (offset +
+                                           offsetof(struct dm_name_list,
+                                           name)), QUOTE_0_TERMINATED);
+                       tprints("}");
+                       if (!s->next)
+                               break;
+                       if (offset + s->next <= offset + (uint32_t)offsetof(struct dm_name_list, name))
+                               goto misplaced;
+                       offset = offset + s->next;
+               } else {
+ misplaced:
+                       tprints(", misplaced struct dm_name_list");
+                       break;
+               }
+       }
+}
+
+static void
+dm_decode_dm_target_versions(const struct dm_ioctl *ioc, const char *extra,
+                            uint32_t extra_size)
+{
+       uint32_t offset = ioc->data_start;
+       while (1) {
+               if (offset + (uint32_t)offsetof(struct dm_target_versions, name) >=
+                   offset &&
+                   offset + (uint32_t)offsetof(struct dm_target_versions, name) <
+                   extra_size) {
+                       const struct dm_target_versions *s =
+                           (const struct dm_target_versions *)(extra + offset);
+                       tprints(", {name=");
+                       print_quoted_string(s->name, extra_size - (offset +
+                                           offsetof(struct dm_target_versions,
+                                           name)), QUOTE_0_TERMINATED);
+                       tprintf(", version=%"PRIu32".%"PRIu32".%"PRIu32"}",
+                               s->version[0], s->version[1], s->version[2]);
+                       if (!s->next)
+                               break;
+                       if (offset + s->next <= offset + (uint32_t)offsetof(struct dm_target_versions, name))
+                               goto misplaced;
+                       offset = offset + s->next;
+               } else {
+ misplaced:
+                       tprints(", misplaced struct dm_target_versions");
+                       break;
+               }
+       }
+}
+
+static void
+dm_decode_dm_target_msg(const struct dm_ioctl *ioc, const char *extra,
+                       uint32_t extra_size)
+{
+       uint32_t offset = ioc->data_start;
+       if (offset + (uint32_t)offsetof(struct dm_target_msg, message) >= offset &&
+           offset + (uint32_t)offsetof(struct dm_target_msg, message) < extra_size) {
+               const struct dm_target_msg *s =
+                       (const struct dm_target_msg *)(extra + offset);
+               tprintf(", {sector=%"PRIu64", message=", (uint64_t)s->sector);
+               print_quoted_string(s->message, extra_size -
+                                   offsetof(struct dm_target_msg, message),
+                                   QUOTE_0_TERMINATED);
+               tprints("}");
+       } else {
+               tprints(", misplaced struct dm_target_msg");
+       }
+}
+
+static void
+dm_decode_string(const struct dm_ioctl *ioc, const char *extra,
+                uint32_t extra_size)
+{
+       uint32_t offset = ioc->data_start;
+       if (offset < extra_size) {
+               tprints(", string=");
+               print_quoted_string(extra + offset, extra_size - offset,
+                                   QUOTE_0_TERMINATED);
+       } else {
+               tprints(", misplaced string");
+       }
+}
+
+static int
+dm_known_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+       struct dm_ioctl ioc;
+       char *extra = NULL;
+       uint32_t extra_size = 0;
+
+       if (umoven(tcp, arg, sizeof(ioc) - sizeof(ioc.data), (char *)&ioc) < 0)
+               return 0;
+       tprintf(", {version=%d.%d.%d", 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)
+               goto skip;
+
+       if (ioc.data_size > sizeof(ioc)) {
+               extra = malloc(ioc.data_size);
+               if (extra) {
+                       extra_size = ioc.data_size;
+                       if (umoven(tcp, arg, extra_size, extra) < 0) {
+                               free(extra);
+                               extra = NULL;
+                               extra_size = 0;
+                       }
+               }
+       }
+       dm_decode_device(code, &ioc);
+       dm_decode_values(tcp, code, &ioc);
+       dm_decode_flags(&ioc);
+       if (!abbrev(tcp)) switch (code) {
+               case DM_DEV_WAIT:
+               case DM_TABLE_STATUS:
+                       if (entering(tcp) || syserror(tcp))
+                               break;
+                       dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size);
+                       break;
+               case DM_TABLE_LOAD:
+                       if (!entering(tcp))
+                               break;
+                       dm_decode_dm_target_spec(tcp, &ioc, extra, extra_size);
+                       break;
+               case DM_TABLE_DEPS:
+                       if (entering(tcp) || syserror(tcp))
+                               break;
+                       dm_decode_dm_target_deps(&ioc, extra, extra_size);
+                       break;
+               case DM_LIST_DEVICES:
+                       if (entering(tcp) || syserror(tcp))
+                               break;
+                       dm_decode_dm_name_list(&ioc, extra, extra_size);
+                       break;
+               case DM_LIST_VERSIONS:
+                       if (entering(tcp) || syserror(tcp))
+                               break;
+                       dm_decode_dm_target_versions(&ioc, extra, extra_size);
+                       break;
+               case DM_TARGET_MSG:
+                       if (entering(tcp)) {
+                               dm_decode_dm_target_msg(&ioc, extra,
+                                                       extra_size);
+                       } else if (!syserror(tcp) &&
+                                  ioc.flags & DM_DATA_OUT_FLAG) {
+                               dm_decode_string(&ioc, extra, extra_size);
+                       }
+                       break;
+               case DM_DEV_RENAME:
+               case DM_DEV_SET_GEOMETRY:
+                       if (!entering(tcp))
+                               break;
+                       dm_decode_string(&ioc, extra, extra_size);
+                       break;
+       }
+
+ skip:
+       tprints("}");
+       if (extra)
+               free(extra);
+       return 1;
+}
+
+int
+dm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+       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:
+               return dm_known_ioctl(tcp, code, arg);
+       default:
+               return 0;
+       }
+}
+
+#endif

Index: strace/ioctl.c
===================================================================

ioctl.c +4 -0
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
        case 0x94:
                return btrfs_ioctl(tcp, code, arg);
 #endif
+#ifdef HAVE_LINUX_DM_IOCTL_H
+       case 0xfd:
+               return dm_ioctl(tcp, code, arg);
+#endif
        default:
                break;
        }

Index: strace/tests/Makefile.am
===================================================================

tests/Makefile.am +2 -0
@@ -161,6 +161,7 @@ check_PROGRAMS = \
        inet-cmsg \
        ioctl \
        ioctl_block \
+       ioctl_dm \
        ioctl_evdev \
        ioctl_evdev-v \
        ioctl_mtd \
@@ -503,6 +504,7 @@ DECODER_TESTS = \
        inet-cmsg.test \
        ioctl.test \
        ioctl_block.test \
+       ioctl_dm.test \
        ioctl_evdev.test \
        ioctl_evdev-v.test \
        ioctl_mtd.test \

Index: strace/tests/ioctl_dm.c
===================================================================

tests/ioctl_dm.c new file +78 -0
@@ -0,0 +1,78 @@
+#include "tests.h"
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <linux/dm-ioctl.h>
+
+static struct s {
+       struct dm_ioctl ioc;
+       union {
+               struct {
+                       struct dm_target_spec target_spec;
+                       char target_params[256];
+               } ts;
+               struct {
+                       struct dm_target_msg target_msg;
+                       char target_string[256];
+               } tm;
+               char string[256];
+       } u;
+} s;
+
+static void init_s(void)
+{
+       memset(&s, 0, sizeof s);
+       s.ioc.version[0] = DM_VERSION_MAJOR;
+       s.ioc.version[1] = 1;
+       s.ioc.version[2] = 2;
+       s.ioc.data_size = sizeof(s);
+       s.ioc.data_start = offsetof(struct s, u);
+       s.ioc.dev = 0x1234;
+       strcpy(s.ioc.name, "nnn");
+       strcpy(s.ioc.uuid, "uuu");
+}
+
+int
+main(void)
+{
+       init_s();
+       s.ioc.data_size = sizeof(s.ioc);
+       s.ioc.data_start = 0;
+       ioctl(-1, DM_VERSION, &s);
+       printf("ioctl(-1, DM_VERSION, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       init_s();
+       s.ioc.target_count = 1;
+       s.u.ts.target_spec.sector_start = 0x10;
+       s.u.ts.target_spec.length = 0x20;
+       s.u.ts.target_spec.next = sizeof(s.u.ts.target_spec) + sizeof(s.u.ts.target_params);
+       strcpy(s.u.ts.target_spec.target_type, "tgt");
+       strcpy(s.u.ts.target_params, "tparams");
+       ioctl(-1, DM_TABLE_LOAD, &s);
+       printf("ioctl(-1, DM_TABLE_LOAD, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", target_count=1, flags=0, {sector_start=16, length=32, target_type=\"tgt\", string=\"tparams\"}}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       init_s();
+       s.u.tm.target_msg.sector = 0x1234;
+       strcpy(s.u.tm.target_msg.message, "tmsg");
+       ioctl(-1, DM_TARGET_MSG, &s);
+       printf("ioctl(-1, DM_TARGET_MSG, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, {sector=4660, message=\"tmsg\"}}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       init_s();
+       strcpy(s.u.string, "10 20 30 40");
+       ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
+       printf("ioctl(-1, DM_DEV_SET_GEOMETRY, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, string=\"10 20 30 40\"}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       init_s();
+       strcpy(s.u.string, "new-name");
+       ioctl(-1, DM_DEV_RENAME, &s);
+       printf("ioctl(-1, DM_DEV_RENAME, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, flags=0, string=\"new-name\"}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       init_s();
+       s.ioc.target_count = -1U;
+       ioctl(-1, DM_TABLE_LOAD, &s);
+       printf("ioctl(-1, DM_TABLE_LOAD, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", target_count=4294967295, flags=0, {sector_start=0, length=0, target_type=\"\", string=\"\"}, misplaced struct dm_target_spec}, {version=4.1.2, dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = -1 EBADF (%m)\n");
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}

Index: strace/tests/ioctl_dm.test
===================================================================

tests/ioctl_dm.test new file +12 -0
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check decoding of DM* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -veioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"

Index: strace/xlat/dm_flags.in
===================================================================

xlat/dm_flags.in new file +17 -1
@@ -0,0 +1,17 @@
+DM_READONLY_FLAG
+DM_SUSPEND_FLAG
+DM_PERSISTENT_DEV_FLAG
+DM_STATUS_TABLE_FLAG
+DM_ACTIVE_PRESENT_FLAG
+DM_INACTIVE_PRESENT_FLAG
+DM_BUFFER_FULL_FLAG
+DM_SKIP_BDGET_FLAG
+DM_SKIP_LOCKFS_FLAG
+DM_NOFLUSH_FLAG
+DM_QUERY_INACTIVE_TABLE_FLAG
+DM_UEVENT_GENERATED_FLAG
+DM_UUID_FLAG
+DM_SECURE_DATA_FLAG
+DM_DATA_OUT_FLAG
+DM_DEFERRED_REMOVE
+DM_INTERNAL_SUSPEND_FLAG
 
------------------------------------------------------------------------------

Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Strace-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Signature · 3 lines
Eugene "eSyr" Syromyatnikov
mailto:[email protected]
xmpp:eSyr@jabber.{ru|org}