Home | History | Annotate | Download | only in tests-m32
      1 /*
      2  * Check decoding of DM_* commands of ioctl syscall.
      3  *
      4  * Copyright (c) 2016 Mikulas Patocka <mpatocka (at) redhat.com>
      5  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr (at) gmail.com>
      6  * Copyright (c) 2016-2018 The strace developers.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "tests.h"
     33 
     34 #ifdef HAVE_LINUX_DM_IOCTL_H
     35 
     36 # include <errno.h>
     37 # include <inttypes.h>
     38 # include <stdbool.h>
     39 # include <stdio.h>
     40 # include <stddef.h>
     41 # include <string.h>
     42 # include <sys/ioctl.h>
     43 # include <linux/ioctl.h>
     44 # include <linux/dm-ioctl.h>
     45 
     46 # ifndef VERBOSE
     47 #  define VERBOSE 0
     48 # endif
     49 
     50 # define STR32 "AbCdEfGhIjKlMnOpQrStUvWxYz012345"
     51 
     52 # define ALIGNED_SIZE(s_, t_) \
     53 	(((s_) + (ALIGNOF(t_) - 1UL)) & ~(ALIGNOF(t_) - 1UL))
     54 # define ALIGNED_OFFSET(t_, m_) \
     55 	ALIGNED_SIZE(offsetof(t_, m_), t_)
     56 
     57 #  ifndef DM_DEV_ARM_POLL
     58 #   define DM_DEV_ARM_POLL     _IOWR(DM_IOCTL, 0x10, struct dm_ioctl)
     59 #  endif
     60 
     61 static const char str129[] = STR32 STR32 STR32 STR32 "6";
     62 
     63 static const __u64 dts_sector_base = (__u64) 0xdeadca75facef157ULL;
     64 static const __u64 dts_sector_step = (__u64) 0x100000001ULL;
     65 static const __u64 dts_length_base = (__u64) 0xbadc0dedda7a1057ULL;
     66 static const __u64 dts_length_step = (__u64) 0x700000007ULL;
     67 static const __s32 dts_status_base = (__s32) 3141592653U;
     68 static const __s32 dts_status_step = 0x1234;
     69 
     70 static const size_t min_sizeof_dm_ioctl =
     71 	offsetof(struct dm_ioctl, data);
     72 
     73 static struct s {
     74 	struct dm_ioctl ioc;
     75 	union {
     76 		struct {
     77 			struct dm_target_spec target_spec;
     78 			char target_params[256];
     79 		} ts;
     80 		struct {
     81 			struct dm_target_msg target_msg;
     82 			char target_string[256];
     83 		} tm;
     84 		char string[256];
     85 	} u;
     86 } s;
     87 
     88 struct dm_table_open_test {
     89 	struct dm_ioctl ioc;
     90 	struct dm_target_spec target0;
     91 	char param0[1];
     92 	struct dm_target_spec target1;
     93 	char param1[2];
     94 	struct dm_target_spec target2;
     95 	char param2[3];
     96 	struct dm_target_spec target3;
     97 	char param3[4];
     98 	struct dm_target_spec target4;
     99 	char param4[5];
    100 	struct dm_target_spec target5;
    101 	char param5[6];
    102 	struct dm_target_spec target6;
    103 	char param6[7];
    104 	struct dm_target_spec target7;
    105 	char param7[8];
    106 	struct dm_target_spec target8;
    107 	char param8[9];
    108 	struct dm_target_spec target9;
    109 	char param9[10];
    110 };
    111 
    112 struct dm_target_msg_test {
    113 	struct dm_ioctl ioc;
    114 	struct dm_target_msg msg;
    115 };
    116 
    117 struct args {
    118 	unsigned int arg;
    119 	const char *str;
    120 	bool has_params;
    121 	bool has_event_nr;
    122 };
    123 
    124 
    125 static void
    126 init_s(struct dm_ioctl *s, size_t size, size_t offs)
    127 {
    128 	memset(s, 0, size);
    129 	s->version[0] = DM_VERSION_MAJOR;
    130 	s->version[1] = 1;
    131 	s->version[2] = 2;
    132 	s->data_size = size;
    133 	s->data_start = offs;
    134 	s->dev = 0x1234;
    135 	strcpy(s->name, "nnn");
    136 	strcpy(s->uuid, "uuu");
    137 }
    138 
    139 static void
    140 init_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
    141 {
    142 	ptr->sector_start = dts_sector_base + dts_sector_step * id;
    143 	ptr->length       = dts_length_base + dts_length_step * id;
    144 	ptr->status       = dts_status_base + dts_status_step * id;
    145 
    146 	memcpy(ptr->target_type, str129 +
    147 		id % (sizeof(str129) - sizeof(ptr->target_type)),
    148 		id % (sizeof(ptr->target_type) + 1));
    149 	if (id % (sizeof(ptr->target_type) + 1) < sizeof(ptr->target_type))
    150 		ptr->target_type[id % (sizeof(ptr->target_type) + 1)] = '\0';
    151 }
    152 
    153 # if VERBOSE
    154 static void
    155 print_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
    156 {
    157 	printf("{sector_start=%" PRI__u64 ", length=%" PRI__u64 ", "
    158 	       "target_type=\"%.*s\", string=",
    159 	       dts_sector_base + dts_sector_step * id,
    160 	       dts_length_base + dts_length_step * id,
    161 	       (int) (id % (sizeof(ptr->target_type) + 1)),
    162 	       str129 + id % (sizeof(str129) - sizeof(ptr->target_type)));
    163 }
    164 # endif /* VERBOSE */
    165 
    166 int
    167 main(void)
    168 {
    169 	static kernel_ulong_t dummy_dm_ioctl1 =
    170 		_IOC(_IOC_READ, DM_IOCTL, 0, 0x1fff);
    171 	static kernel_ulong_t dummy_dm_ioctl2 =
    172 		_IOC(_IOC_READ|_IOC_WRITE, DM_IOCTL, 0xed, 0);
    173 	static kernel_ulong_t dummy_dm_arg =
    174 		(kernel_ulong_t) 0xbadc0dedda7a1057ULL;
    175 	/* We can't check these properly for now */
    176 	static struct args dummy_check_cmds_nodev[] = {
    177 		{ ARG_STR(DM_REMOVE_ALL),    false },
    178 		{ ARG_STR(DM_LIST_DEVICES),  true  },
    179 		{ ARG_STR(DM_LIST_VERSIONS), true  },
    180 	};
    181 	static struct args dummy_check_cmds[] = {
    182 		{ ARG_STR(DM_DEV_CREATE),    false },
    183 		{ ARG_STR(DM_DEV_REMOVE),    false, true },
    184 		{ ARG_STR(DM_DEV_STATUS),    false },
    185 		{ ARG_STR(DM_DEV_WAIT),      true,  true },
    186 		{ ARG_STR(DM_TABLE_CLEAR),   false },
    187 		{ ARG_STR(DM_TABLE_DEPS),    true  },
    188 		{ ARG_STR(DM_TABLE_STATUS),  true  },
    189 		{ ARG_STR(DM_DEV_ARM_POLL),  false },
    190 	};
    191 
    192 	struct dm_ioctl *unaligned_dm_arg =
    193 		tail_alloc(offsetof(struct dm_ioctl, data));
    194 	struct dm_ioctl *dm_arg =
    195 		tail_alloc(ALIGNED_OFFSET(struct dm_ioctl, data));
    196 	struct dm_table_open_test *dm_arg_open1 =
    197 		tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, target1));
    198 	struct dm_table_open_test *dm_arg_open2 =
    199 		tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, param1));
    200 	struct dm_table_open_test *dm_arg_open3 =
    201 		tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, target9));
    202 	struct dm_target_msg_test *dm_arg_msg =
    203 		tail_alloc(sizeof(*dm_arg_msg));
    204 
    205 	long rc;
    206 	const char *errstr;
    207 	unsigned int i;
    208 
    209 
    210 	/* Incorrect operation */
    211 	ioctl(-1, _IOW(DM_IOCTL, 0xde, int), dm_arg);
    212 	printf("ioctl(-1, _IOC(_IOC_WRITE, %#x, 0xde, %#zx), %p) = "
    213 	       "-1 EBADF (%m)\n",
    214 	       DM_IOCTL, sizeof(int), dm_arg);
    215 
    216 	ioctl(-1, dummy_dm_ioctl1, 0);
    217 	printf("ioctl(-1, _IOC(_IOC_READ, %#x, 0, %#x), 0) = -1 EBADF (%m)\n",
    218 	       DM_IOCTL, (unsigned int) _IOC_SIZE(dummy_dm_ioctl1));
    219 
    220 	ioctl(-1, dummy_dm_ioctl2, dummy_dm_arg);
    221 	printf("ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, %#x, %#x, 0), %#lx) = "
    222 	       "-1 EBADF (%m)\n",
    223 	       DM_IOCTL, (unsigned int) _IOC_NR(dummy_dm_ioctl2),
    224 	       (unsigned long) dummy_dm_arg);
    225 
    226 
    227 	/* DM_VERSION */
    228 	/* Incorrect pointer */
    229 	ioctl(-1, DM_VERSION, dm_arg + 1);
    230 	printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", dm_arg + 1);
    231 
    232 	/* Incorrect data_size */
    233 	init_s(dm_arg, 0, 0);
    234 	ioctl(-1, DM_VERSION, &s);
    235 	printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", &s);
    236 
    237 	/* Incorrect version */
    238 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    239 	dm_arg->version[0] = 0xbadc0ded;
    240 	dm_arg->version[1] = 0xbadc0dee;
    241 	dm_arg->version[2] = 0xbadc0def;
    242 	ioctl(-1, DM_VERSION, dm_arg);
    243 	printf("ioctl(-1, DM_VERSION, {version=%u.%u.%u"
    244 	       " /* unsupported device mapper ABI version */}) = "
    245 	       "-1 EBADF (%m)\n", 0xbadc0ded, 0xbadc0dee, 0xbadc0def);
    246 
    247 	/* Incorrect data_size */
    248 	init_s(dm_arg, 14, 64);
    249 	ioctl(-1, DM_VERSION, dm_arg);
    250 	printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=14"
    251 	       " /* data_size too small */}) = -1 EBADF (%m)\n");
    252 
    253 	/* Unterminated name/uuid */
    254 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    255 	memcpy(dm_arg->name, str129, sizeof(dm_arg->name));
    256 	memcpy(dm_arg->uuid, str129, sizeof(dm_arg->uuid));
    257 	ioctl(-1, DM_VERSION, dm_arg);
    258 	printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=%zu, "
    259 	       "dev=makedev(18, 52), name=\"%.127s\"..., uuid=\"%.128s\"..., "
    260 	       "flags=0}) = -1 EBADF (%m)\n",
    261 	       min_sizeof_dm_ioctl, str129, str129);
    262 
    263 	/* Normal call */
    264 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    265 	ioctl(-1, DM_VERSION, dm_arg);
    266 	printf("ioctl(-1, DM_VERSION, "
    267 	       "{version=4.1.2, data_size=%zu, "
    268 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
    269 	       "-1 EBADF (%m)\n", min_sizeof_dm_ioctl);
    270 
    271 	/* Zero dev, name, uuid */
    272 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    273 	dm_arg->data_size = 0xfacefeed;
    274 	dm_arg->dev = 0;
    275 	dm_arg->name[0] = '\0';
    276 	dm_arg->uuid[0] = '\0';
    277 	ioctl(-1, DM_VERSION, dm_arg);
    278 	printf("ioctl(-1, DM_VERSION, "
    279 	       "{version=4.1.2, data_size=%u, flags=0}) = "
    280 	       "-1 EBADF (%m)\n", 0xfacefeed);
    281 
    282 	/* Flag */
    283 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    284 	dm_arg->flags = 0xffffffff;
    285 	ioctl(-1, DM_VERSION, dm_arg);
    286 	printf("ioctl(-1, DM_VERSION, "
    287 	       "{version=4.1.2, data_size=%zu, "
    288 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags="
    289 	       "DM_READONLY_FLAG|DM_SUSPEND_FLAG|DM_EXISTS_FLAG|"
    290 	       "DM_PERSISTENT_DEV_FLAG|DM_STATUS_TABLE_FLAG|"
    291 	       "DM_ACTIVE_PRESENT_FLAG|DM_INACTIVE_PRESENT_FLAG|"
    292 	       "DM_BUFFER_FULL_FLAG|DM_SKIP_BDGET_FLAG|DM_SKIP_LOCKFS_FLAG|"
    293 	       "DM_NOFLUSH_FLAG|DM_QUERY_INACTIVE_TABLE_FLAG|"
    294 	       "DM_UEVENT_GENERATED_FLAG|DM_UUID_FLAG|DM_SECURE_DATA_FLAG|"
    295 	       "DM_DATA_OUT_FLAG|DM_DEFERRED_REMOVE|DM_INTERNAL_SUSPEND_FLAG|"
    296 	       "0xfff80080}) = -1 EBADF (%m)\n",
    297 	       min_sizeof_dm_ioctl);
    298 
    299 	/* Normal call */
    300 	init_s(&s.ioc, sizeof(s.ioc), 0);
    301 	ioctl(-1, DM_VERSION, &s);
    302 	printf("ioctl(-1, DM_VERSION, "
    303 	       "{version=4.1.2, data_size=%zu, "
    304 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
    305 	       "-1 EBADF (%m)\n", sizeof(s.ioc));
    306 
    307 
    308 	/* DM_REMOVE_ALL */
    309 	/* DM_LIST_DEVICES */
    310 	/* DM_LIST_VERSIONS */
    311 	for (i = 0; i < ARRAY_SIZE(dummy_check_cmds_nodev); i++) {
    312 		init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    313 		ioctl(-1, dummy_check_cmds_nodev[i].arg, dm_arg);
    314 		printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
    315 		       "flags=0}) = -1 EBADF (%m)\n",
    316 		       dummy_check_cmds_nodev[i].str,
    317 		       min_sizeof_dm_ioctl,
    318 		       dummy_check_cmds_nodev[i].has_params ?
    319 		       ", data_start=0" : "");
    320 	}
    321 
    322 
    323 	/* DM_DEV_CREATE */
    324 	/* DM_DEV_REMOVE */
    325 	/* DM_DEV_STATUS */
    326 	/* DM_DEV_WAIT */
    327 	/* DM_TABLE_CLEAR */
    328 	/* DM_TABLE_DEPS */
    329 	/* DM_TABLE_STATUS */
    330 	for (i = 0; i < ARRAY_SIZE(dummy_check_cmds); i++) {
    331 		init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    332 		ioctl(-1, dummy_check_cmds[i].arg, dm_arg);
    333 		printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
    334 		       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\"%s, "
    335 		       "flags=0}) = -1 EBADF (%m)\n",
    336 		       dummy_check_cmds[i].str, min_sizeof_dm_ioctl,
    337 		       dummy_check_cmds[i].has_params ? ", data_start=0" : "",
    338 		       dummy_check_cmds[i].has_event_nr ? ", event_nr=0" : "");
    339 	}
    340 
    341 
    342 	/* DM_DEV_SUSPEND */
    343 	init_s(&s.ioc, sizeof(s.ioc), 0);
    344 	s.ioc.flags = DM_SUSPEND_FLAG;
    345 	s.ioc.event_nr = 0xbadc0ded;
    346 	ioctl(-1, DM_DEV_SUSPEND, &s);
    347 	printf("ioctl(-1, DM_DEV_SUSPEND, "
    348 	       "{version=4.1.2, data_size=%zu, "
    349 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    350 	       "flags=DM_SUSPEND_FLAG}) = -1 EBADF (%m)\n", sizeof(s.ioc));
    351 
    352 	init_s(&s.ioc, sizeof(s.ioc), 0);
    353 	s.ioc.event_nr = 0xbadc0ded;
    354 	ioctl(-1, DM_DEV_SUSPEND, &s);
    355 	printf("ioctl(-1, DM_DEV_SUSPEND, "
    356 	       "{version=4.1.2, data_size=%zu, dev=makedev(18, 52), "
    357 	       "name=\"nnn\", uuid=\"uuu\", event_nr=3134983661, "
    358 	       "flags=0}) = -1 EBADF (%m)\n", sizeof(s.ioc));
    359 
    360 
    361 	/* DM_TABLE_LOAD */
    362 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    363 	s.ioc.target_count = 1;
    364 	s.u.ts.target_spec.sector_start = 0x10;
    365 	s.u.ts.target_spec.length = 0x20;
    366 	s.u.ts.target_spec.next =
    367 		sizeof(s.u.ts.target_spec) + sizeof(s.u.ts.target_params);
    368 	strcpy(s.u.ts.target_spec.target_type, "tgt");
    369 	strcpy(s.u.ts.target_params, "tparams");
    370 	ioctl(-1, DM_TABLE_LOAD, &s);
    371 	printf("ioctl(-1, DM_TABLE_LOAD, "
    372 	       "{version=4.1.2, data_size=%u, data_start=%u, "
    373 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    374 	       "target_count=1, flags=0, "
    375 # if VERBOSE
    376 	       "{sector_start=16, length=32, target_type=\"tgt\", "
    377 	       "string=\"tparams\"}"
    378 # else /* !VERBOSE */
    379 	       "..."
    380 # endif /* VERBOSE */
    381 	       "}) = -1 EBADF (%m)\n", s.ioc.data_size, s.ioc.data_start);
    382 
    383 	/* No targets */
    384 	init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
    385 	dm_arg->data_size = sizeof(*dm_arg);
    386 	dm_arg->target_count = 0;
    387 	ioctl(-1, DM_TABLE_LOAD, dm_arg);
    388 	printf("ioctl(-1, DM_TABLE_LOAD, "
    389 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    390 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    391 	       "target_count=0, flags=0}) = -1 EBADF (%m)\n",
    392 	       sizeof(*dm_arg), min_sizeof_dm_ioctl);
    393 
    394 	/* Invalid data_start */
    395 	init_s(dm_arg, min_sizeof_dm_ioctl, 0xfffffff8);
    396 	dm_arg->data_size = sizeof(*dm_arg);
    397 	dm_arg->target_count = 1234;
    398 	ioctl(-1, DM_TABLE_LOAD, dm_arg);
    399 	printf("ioctl(-1, DM_TABLE_LOAD, "
    400 	       "{version=4.1.2, data_size=%zu, data_start=%u, "
    401 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    402 	       "target_count=1234, flags=0, "
    403 # if VERBOSE
    404 	       "??? /* misplaced struct dm_target_spec */"
    405 # else
    406 	       "..."
    407 # endif /* VERBOSE */
    408 	       "}) = -1 EBADF (%m)\n", sizeof(*dm_arg), 0xfffffff8);
    409 
    410 	/* Inaccessible pointer */
    411 	init_s(&dm_arg_open1->ioc, offsetof(struct dm_table_open_test, target1),
    412 	       offsetof(struct dm_table_open_test, target1));
    413 	dm_arg_open1->ioc.data_size = sizeof(*dm_arg_open1);
    414 	dm_arg_open1->ioc.target_count = 0xdeaddea1;
    415 	ioctl(-1, DM_TABLE_LOAD, dm_arg_open1);
    416 	printf("ioctl(-1, DM_TABLE_LOAD, "
    417 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    418 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    419 	       "target_count=3735936673, flags=0, "
    420 # if VERBOSE
    421 	       "%p"
    422 # else /* !VERBOSE */
    423 	       "..."
    424 # endif /* VERBOSE */
    425 	       "}) = -1 EBADF (%m)\n", sizeof(*dm_arg_open1),
    426 	       offsetof(struct dm_table_open_test, target1)
    427 # if VERBOSE
    428 	       , (char *) dm_arg_open1 +
    429 	       offsetof(struct dm_table_open_test, target1)
    430 # endif /* VERBOSE */
    431 	       );
    432 
    433 	/* Inaccessible string */
    434 	init_s(&dm_arg_open2->ioc, offsetof(struct dm_table_open_test, param1),
    435 	       offsetof(struct dm_table_open_test, target1));
    436 	dm_arg_open2->ioc.data_size = sizeof(*dm_arg_open2);
    437 	dm_arg_open2->ioc.target_count = 2;
    438 	init_dm_target_spec(&dm_arg_open2->target1, 7);
    439 	dm_arg_open2->target1.next =
    440 		offsetof(struct dm_table_open_test, target3) -
    441 		offsetof(struct dm_table_open_test, target1);
    442 	rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open2);
    443 	errstr = sprintrc(rc);
    444 	printf("ioctl(-1, DM_TABLE_LOAD, "
    445 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    446 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    447 	       "target_count=2, flags=0, ",
    448 	       sizeof(*dm_arg_open2),
    449 	       offsetof(struct dm_table_open_test, target1));
    450 # if VERBOSE
    451 	print_dm_target_spec(&dm_arg_open2->target1, 7);
    452 	printf("%p}, %p",
    453 	       (char *) dm_arg_open2 +
    454 	       offsetof(struct dm_table_open_test, param1),
    455 	       (char *) dm_arg_open2 +
    456 	       offsetof(struct dm_table_open_test, target3));
    457 # else /* !VERBOSE */
    458 	printf("...");
    459 # endif /* VERBOSE */
    460 	printf("}) = %s\n", errstr);
    461 
    462 	/* Incorrect next */
    463 	init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target5),
    464 	       offsetof(struct dm_table_open_test, target0));
    465 	dm_arg_open3->ioc.target_count = 4;
    466 
    467 	init_dm_target_spec(&dm_arg_open3->target0, 9);
    468 	dm_arg_open3->target0.next =
    469 		offsetof(struct dm_table_open_test, target1) -
    470 		offsetof(struct dm_table_open_test, target0);
    471 	dm_arg_open3->param0[0] = '\0';
    472 
    473 	init_dm_target_spec(&dm_arg_open3->target1, 15);
    474 	dm_arg_open3->target1.next =
    475 		offsetof(struct dm_table_open_test, target3) -
    476 		offsetof(struct dm_table_open_test, target1);
    477 	dm_arg_open3->param1[0] = '\377';
    478 	dm_arg_open3->param1[1] = '\0';
    479 
    480 	init_dm_target_spec(&dm_arg_open3->target3, 42);
    481 	dm_arg_open3->target3.next = 0xdeadbeef;
    482 	dm_arg_open3->param3[0] = '\1';
    483 	dm_arg_open3->param3[1] = '\2';
    484 	dm_arg_open3->param3[2] = '\0';
    485 
    486 	rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
    487 	errstr = sprintrc(rc);
    488 	printf("ioctl(-1, DM_TABLE_LOAD, "
    489 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    490 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    491 	       "target_count=4, flags=0, ",
    492 	       offsetof(struct dm_table_open_test, target5),
    493 	       offsetof(struct dm_table_open_test, target0));
    494 # if VERBOSE
    495 	print_dm_target_spec(&dm_arg_open3->target0, 9);
    496 	printf("\"\"}, ");
    497 	print_dm_target_spec(&dm_arg_open3->target1, 15);
    498 	printf("\"\\377\"}, ");
    499 	print_dm_target_spec(&dm_arg_open3->target1, 42);
    500 	printf("\"\\1\\2\"}, ??? /* misplaced struct dm_target_spec */");
    501 # else /* !VERBOSE */
    502 	printf("...");
    503 # endif /* VERBOSE */
    504 	printf("}) = %s\n", errstr);
    505 
    506 	#define FILL_DM_TARGET(id, id_next) \
    507 		do { \
    508 			init_dm_target_spec(&dm_arg_open3->target##id, id); \
    509 			dm_arg_open3->target##id.next = \
    510 				offsetof(struct dm_table_open_test, \
    511 					 target##id_next) - \
    512 				offsetof(struct dm_table_open_test, \
    513 					 target##id); \
    514 			memcpy(dm_arg_open3->param##id, str129 + id * 2, id); \
    515 			dm_arg_open3->param##id[id] = '\0'; \
    516 		} while (0)
    517 	#define PRINT_DM_TARGET(id) \
    518 		do { \
    519 			print_dm_target_spec(&dm_arg_open3->target##id, id); \
    520 			printf("\"%.*s\"}, ", id, str129 + id * 2); \
    521 		} while (0)
    522 
    523 	/* max_strlen limit */
    524 	init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target9),
    525 	       offsetof(struct dm_table_open_test, target0));
    526 	dm_arg_open3->ioc.data_size = sizeof(*dm_arg_open3);
    527 	dm_arg_open3->ioc.target_count = 0xbadc0ded;
    528 	FILL_DM_TARGET(0, 1);
    529 	FILL_DM_TARGET(1, 2);
    530 	FILL_DM_TARGET(2, 3);
    531 	FILL_DM_TARGET(3, 4);
    532 	FILL_DM_TARGET(4, 5);
    533 	FILL_DM_TARGET(5, 6);
    534 	FILL_DM_TARGET(6, 7);
    535 	FILL_DM_TARGET(7, 8);
    536 	FILL_DM_TARGET(8, 9);
    537 	rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
    538 	errstr = sprintrc(rc);
    539 	printf("ioctl(-1, DM_TABLE_LOAD, "
    540 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    541 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    542 	       "target_count=3134983661, flags=0, ",
    543 	       sizeof(*dm_arg_open3),
    544 	       offsetof(struct dm_table_open_test, target0));
    545 # if VERBOSE
    546 	PRINT_DM_TARGET(0);
    547 	PRINT_DM_TARGET(1);
    548 	PRINT_DM_TARGET(2);
    549 	PRINT_DM_TARGET(3);
    550 	PRINT_DM_TARGET(4);
    551 	PRINT_DM_TARGET(5);
    552 	PRINT_DM_TARGET(6);
    553 	PRINT_DM_TARGET(7);
    554 	PRINT_DM_TARGET(8);
    555 # endif /* VERBOSE */
    556 	printf("...}) = %s\n", errstr);
    557 
    558 
    559 	/* DM_TARGET_MSG */
    560 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    561 	s.u.tm.target_msg.sector = 0x1234;
    562 	strcpy(s.u.string + offsetof(struct dm_target_msg, message),
    563 	       "long target msg");
    564 	ioctl(-1, DM_TARGET_MSG, &s);
    565 	printf("ioctl(-1, DM_TARGET_MSG, "
    566 	       "{version=4.1.2, data_size=%u, data_start=%u, "
    567 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
    568 # if VERBOSE
    569 	       "{sector=4660, message=\"long targ\"...}"
    570 # else /* !VERBOSE */
    571 	       "..."
    572 # endif /* VERBOSE */
    573 	       "}) = -1 EBADF (%m)\n",
    574 	       s.ioc.data_size, s.ioc.data_start);
    575 
    576 	/* Invalid data_start */
    577 	init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
    578 	dm_arg->data_size = sizeof(*dm_arg);
    579 	ioctl(-1, DM_TARGET_MSG, dm_arg);
    580 	printf("ioctl(-1, DM_TARGET_MSG, "
    581 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    582 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
    583 # if VERBOSE
    584 	       "??? /* misplaced struct dm_target_msg */"
    585 # else /* !VERBOSE */
    586 	       "..."
    587 # endif /* VERBOSE */
    588 	       "}) = -1 EBADF (%m)\n",
    589 	       sizeof(*dm_arg), min_sizeof_dm_ioctl);
    590 
    591 	/* Invalid data_start */
    592 	init_s(dm_arg, min_sizeof_dm_ioctl, 0xffffffff);
    593 	dm_arg->data_size = sizeof(*dm_arg);
    594 	ioctl(-1, DM_TARGET_MSG, dm_arg);
    595 	printf("ioctl(-1, DM_TARGET_MSG, "
    596 	       "{version=4.1.2, data_size=%zu, data_start=%u, "
    597 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
    598 # if VERBOSE
    599 	       "??? /* misplaced struct dm_target_msg */"
    600 # else /* !VERBOSE */
    601 	       "..."
    602 # endif /* VERBOSE */
    603 	       "}) = -1 EBADF (%m)\n",
    604 	       sizeof(*dm_arg), 0xffffffff);
    605 
    606 	/* Inaccessible pointer */
    607 	init_s(dm_arg, min_sizeof_dm_ioctl, 0);
    608 	dm_arg->data_size = sizeof(*dm_arg) + sizeof(struct dm_target_msg);
    609 	dm_arg->data_start = sizeof(*dm_arg);
    610 	ioctl(-1, DM_TARGET_MSG, dm_arg);
    611 	printf("ioctl(-1, DM_TARGET_MSG, "
    612 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    613 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
    614 # if VERBOSE
    615 	       "%p"
    616 # else /* !VERBOSE */
    617 	       "..."
    618 # endif /* VERBOSE */
    619 	       "}) = -1 EBADF (%m)\n",
    620 	       sizeof(*dm_arg) + sizeof(struct dm_target_msg),
    621 	       sizeof(*dm_arg)
    622 # if VERBOSE
    623 	       , (char *) dm_arg + sizeof(*dm_arg)
    624 # endif /* VERBOSE */
    625 	       );
    626 
    627 	/* Inaccessible string */
    628 	init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
    629 	       offsetof(struct dm_target_msg_test, msg));
    630 	dm_arg_msg->ioc.data_size = sizeof(*dm_arg_msg) + 1;
    631 	dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
    632 	rc = ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
    633 	errstr = sprintrc(rc);
    634 	printf("ioctl(-1, DM_TARGET_MSG, "
    635 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    636 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, ",
    637 	       sizeof(*dm_arg_msg) + 1,
    638 	       offsetof(struct dm_target_msg_test, msg));
    639 # if VERBOSE
    640 	printf("{sector=%" PRI__u64 ", message=%p}",
    641 	       (__u64) 0xdeadbeeffacef157ULL,
    642 	       (char *) dm_arg_msg +
    643 	       offsetof(struct dm_target_msg_test, msg.message));
    644 # else /* !VERBOSE */
    645 	printf("...");
    646 # endif /* VERBOSE */
    647 	printf("}) = %s\n", errstr);
    648 
    649 	/* Zero-sied string */
    650 	init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
    651 	       offsetof(struct dm_target_msg_test, msg));
    652 	dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
    653 	rc = ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
    654 	errstr = sprintrc(rc);
    655 	printf("ioctl(-1, DM_TARGET_MSG, "
    656 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    657 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, ",
    658 	       sizeof(*dm_arg_msg), offsetof(struct dm_target_msg_test, msg));
    659 # if VERBOSE
    660 	printf("{sector=%" PRI__u64 ", message=\"\"}",
    661 	       (__u64) 0xdeadbeeffacef157ULL);
    662 # else /* !VERBOSE */
    663 	printf("...");
    664 # endif /* VERBOSE */
    665 	printf("}) = %s\n", errstr);
    666 
    667 
    668 	/* DM_DEV_SET_GEOMETRY */
    669 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    670 	strcpy(s.u.string, "10 20 30 40");
    671 	ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
    672 	printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
    673 	       "{version=4.1.2, data_size=%u, data_start=%u, "
    674 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
    675 # if VERBOSE
    676 	       "string=\"10 20 30 \"..."
    677 # else /* !VERBOSE */
    678 	       "..."
    679 # endif /* VERBOSE */
    680 	       "}) = -1 EBADF (%m)\n",
    681 	       s.ioc.data_size, s.ioc.data_start);
    682 
    683 
    684 	/* DM_DEV_RENAME */
    685 	/* Inaccessible data */
    686 	init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
    687 	dm_arg->data_size = sizeof(*dm_arg);
    688 	memcpy(unaligned_dm_arg, dm_arg, offsetof(struct dm_ioctl, data));
    689 	ioctl(-1, DM_DEV_RENAME, unaligned_dm_arg);
    690 	printf("ioctl(-1, DM_DEV_RENAME, "
    691 	       "{version=4.1.2, data_size=%zu, data_start=%zu, "
    692 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
    693 	       "flags=0, "
    694 # if VERBOSE
    695 	       "string=%p"
    696 # else /* !VERBOSE */
    697 	       "..."
    698 # endif /* VERBOSE */
    699 	       "}) = -1 EBADF (%m)\n",
    700 	       sizeof(*unaligned_dm_arg), min_sizeof_dm_ioctl
    701 # if VERBOSE
    702 	       , (char *) unaligned_dm_arg + min_sizeof_dm_ioctl
    703 # endif /* VERBOSE */
    704 	       );
    705 
    706 	/* Incorrect data_start data */
    707 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    708 	s.ioc.data_start = 0xdeadbeef;
    709 	ioctl(-1, DM_DEV_RENAME, &s);
    710 	printf("ioctl(-1, DM_DEV_RENAME, "
    711 	       "{version=4.1.2, data_size=%u, data_start=3735928559, "
    712 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
    713 	       "flags=0, "
    714 # if VERBOSE
    715 	       "??? /* misplaced string */"
    716 # else /* !VERBOSE */
    717 	       "..."
    718 # endif /* VERBOSE */
    719 	       "}) = -1 EBADF (%m)\n",
    720 	       s.ioc.data_size);
    721 
    722 	/* Strange but still valid data_start */
    723 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    724 	/* Curiously, this is a valid structure */
    725 	s.ioc.data_start = offsetof(struct dm_ioctl, name) + 1;
    726 	ioctl(-1, DM_DEV_RENAME, &s);
    727 	printf("ioctl(-1, DM_DEV_RENAME, "
    728 	       "{version=4.1.2, data_size=%u, data_start=%zu, "
    729 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
    730 	       "flags=0, "
    731 # if VERBOSE
    732 	       "string=\"nn\""
    733 # else /* !VERBOSE */
    734 	       "..."
    735 # endif /* VERBOSE */
    736 	       "}) = -1 EBADF (%m)\n",
    737 	       s.ioc.data_size,
    738 	       offsetof(struct dm_ioctl, name) + 1);
    739 
    740 	/* Correct data */
    741 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    742 	strcpy(s.u.string, "new long name");
    743 	ioctl(-1, DM_DEV_RENAME, &s);
    744 	printf("ioctl(-1, DM_DEV_RENAME, "
    745 	       "{version=4.1.2, data_size=%u, data_start=%u, "
    746 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
    747 	       "flags=0, "
    748 # if VERBOSE
    749 	       "string=\"new long \"..."
    750 # else /* !VERBOSE */
    751 	       "..."
    752 # endif /* VERBOSE */
    753 	       "}) = -1 EBADF (%m)\n",
    754 	       s.ioc.data_size, s.ioc.data_start);
    755 
    756 
    757 	/* DM_TABLE_LOAD */
    758 	init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
    759 	s.ioc.target_count = -1U;
    760 	ioctl(-1, DM_TABLE_LOAD, &s);
    761 	printf("ioctl(-1, DM_TABLE_LOAD, "
    762 	       "{version=4.1.2, data_size=%u, data_start=%u, "
    763 	       "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
    764 	       "target_count=4294967295, flags=0, "
    765 # if VERBOSE
    766 	       "{sector_start=0, length=0, target_type=\"\", string=\"\"}"
    767 	       ", ??? /* misplaced struct dm_target_spec */"
    768 # else
    769 	       "..."
    770 # endif /* VERBOSE */
    771 	       "}) = -1 EBADF (%m)\n",
    772 	       s.ioc.data_size, s.ioc.data_start);
    773 
    774 	puts("+++ exited with 0 +++");
    775 	return 0;
    776 }
    777 
    778 #else /* !HAVE_LINUX_DM_IOCTL_H */
    779 
    780 SKIP_MAIN_UNDEFINED("HAVE_LINUX_DM_IOCTL_H")
    781 
    782 #endif /* HAVE_LINUX_DM_IOCTL_H */
    783