2 * Check decoding of DM_* commands of ioctl syscall.
4 * Copyright (c) 2016 Mikulas Patocka <mpatocka@redhat.com>
5 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #ifdef HAVE_LINUX_DM_IOCTL_H
36 # include <inttypes.h>
41 # include <sys/ioctl.h>
42 # include <linux/dm-ioctl.h>
48 # define STR32 "AbCdEfGhIjKlMnOpQrStUvWxYz012345"
50 # define ALIGNED_SIZE(s_, t_) \
51 (((s_) + (ALIGNOF(t_) - 1UL)) & ~(ALIGNOF(t_) - 1UL))
52 # define ALIGNED_OFFSET(t_, m_) \
53 ALIGNED_SIZE(offsetof(t_, m_), t_)
55 static const char str129[] = STR32 STR32 STR32 STR32 "6";
57 static const __u64 dts_sector_base = (__u64) 0xdeadca75facef157ULL;
58 static const __u64 dts_sector_step = (__u64) 0x100000001ULL;
59 static const __u64 dts_length_base = (__u64) 0xbadc0dedda7a1057ULL;
60 static const __u64 dts_length_step = (__u64) 0x700000007ULL;
61 static const __s32 dts_status_base = (__s32) 3141592653U;
62 static const __s32 dts_status_step = 0x1234;
64 static const size_t min_sizeof_dm_ioctl =
65 offsetof(struct dm_ioctl, data);
71 struct dm_target_spec target_spec;
72 char target_params[256];
75 struct dm_target_msg target_msg;
76 char target_string[256];
82 struct dm_table_open_test {
84 struct dm_target_spec target0;
86 struct dm_target_spec target1;
88 struct dm_target_spec target2;
90 struct dm_target_spec target3;
92 struct dm_target_spec target4;
94 struct dm_target_spec target5;
96 struct dm_target_spec target6;
98 struct dm_target_spec target7;
100 struct dm_target_spec target8;
102 struct dm_target_spec target9;
106 struct dm_target_msg_test {
108 struct dm_target_msg msg;
120 init_s(struct dm_ioctl *s, size_t size, size_t offs)
123 s->version[0] = DM_VERSION_MAJOR;
127 s->data_start = offs;
129 strcpy(s->name, "nnn");
130 strcpy(s->uuid, "uuu");
134 init_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
136 ptr->sector_start = dts_sector_base + dts_sector_step * id;
137 ptr->length = dts_length_base + dts_length_step * id;
138 ptr->status = dts_status_base + dts_status_step * id;
140 strncpy(ptr->target_type, str129 +
141 id % (sizeof(str129) - sizeof(ptr->target_type)),
142 id % (sizeof(ptr->target_type) + 1));
143 if (id % (sizeof(ptr->target_type) + 1) < sizeof(ptr->target_type))
144 ptr->target_type[id % (sizeof(ptr->target_type) + 1)] = '\0';
149 print_dm_target_spec(struct dm_target_spec *ptr, uint32_t id)
151 printf("{sector_start=%" PRI__u64 ", length=%" PRI__u64 ", "
152 "target_type=\"%.*s\", string=",
153 dts_sector_base + dts_sector_step * id,
154 dts_length_base + dts_length_step * id,
155 (int) (id % (sizeof(ptr->target_type) + 1)),
156 str129 + id % (sizeof(str129) - sizeof(ptr->target_type)));
158 # endif /* VERBOSE */
163 /* We can't check these properly for now */
164 static struct args dummy_check_cmds_nodev[] = {
165 { ARG_STR(DM_REMOVE_ALL), false },
166 { ARG_STR(DM_LIST_DEVICES), true },
167 { ARG_STR(DM_LIST_VERSIONS), true },
169 static struct args dummy_check_cmds[] = {
170 { ARG_STR(DM_DEV_CREATE), false },
171 { ARG_STR(DM_DEV_REMOVE), false, true },
172 { ARG_STR(DM_DEV_STATUS), false },
173 { ARG_STR(DM_DEV_WAIT), true, true },
174 { ARG_STR(DM_TABLE_CLEAR), false },
175 { ARG_STR(DM_TABLE_DEPS), true },
176 { ARG_STR(DM_TABLE_STATUS), true },
179 struct dm_ioctl *unaligned_dm_arg =
180 tail_alloc(offsetof(struct dm_ioctl, data));
181 struct dm_ioctl *dm_arg =
182 tail_alloc(ALIGNED_OFFSET(struct dm_ioctl, data));
183 struct dm_table_open_test *dm_arg_open1 =
184 tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, target1));
185 struct dm_table_open_test *dm_arg_open2 =
186 tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, param1));
187 struct dm_table_open_test *dm_arg_open3 =
188 tail_alloc(ALIGNED_OFFSET(struct dm_table_open_test, target9));
189 struct dm_target_msg_test *dm_arg_msg =
190 tail_alloc(sizeof(*dm_arg_msg));
197 /* Incorrect operation */
198 ioctl(-1, _IOW(DM_IOCTL, 0xde, int), dm_arg);
199 printf("ioctl(-1, _IOC(_IOC_WRITE, %#04x, 0xde, %#04zx), %p) = "
201 DM_IOCTL, sizeof(int), dm_arg);
205 /* Incorrect pointer */
206 ioctl(-1, DM_VERSION, dm_arg + 1);
207 printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", dm_arg + 1);
209 /* Incorrect data_size */
210 init_s(dm_arg, 0, 0);
211 ioctl(-1, DM_VERSION, &s);
212 printf("ioctl(-1, DM_VERSION, %p) = -1 EBADF (%m)\n", &s);
214 /* Incorrect version */
215 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
216 dm_arg->version[0] = 0xbadc0ded;
217 dm_arg->version[1] = 0xbadc0dee;
218 dm_arg->version[2] = 0xbadc0def;
219 ioctl(-1, DM_VERSION, dm_arg);
220 printf("ioctl(-1, DM_VERSION, {version=%u.%u.%u, "
221 "/* Unsupported device mapper ABI version */ ...}) = "
222 "-1 EBADF (%m)\n", 0xbadc0ded, 0xbadc0dee, 0xbadc0def);
224 /* Incorrect data_size */
225 init_s(dm_arg, 14, 64);
226 ioctl(-1, DM_VERSION, dm_arg);
227 printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=14, "
228 "/* Incorrect data_size */ ...}) = -1 EBADF (%m)\n");
230 /* Unterminated name/uuid */
231 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
232 strncpy(dm_arg->name, str129, sizeof(dm_arg->name));
233 strncpy(dm_arg->uuid, str129, sizeof(dm_arg->uuid));
234 ioctl(-1, DM_VERSION, dm_arg);
235 printf("ioctl(-1, DM_VERSION, {version=4.1.2, data_size=%zu, "
236 "dev=makedev(18, 52), name=\"%.127s\", uuid=\"%.128s\", "
237 "flags=0}) = -1 EBADF (%m)\n",
238 min_sizeof_dm_ioctl, str129, str129);
241 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
242 ioctl(-1, DM_VERSION, dm_arg);
243 printf("ioctl(-1, DM_VERSION, "
244 "{version=4.1.2, data_size=%zu, "
245 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
246 "-1 EBADF (%m)\n", min_sizeof_dm_ioctl);
248 /* Zero dev, name, uuid */
249 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
250 dm_arg->data_size = 0xfacefeed;
252 dm_arg->name[0] = '\0';
253 dm_arg->uuid[0] = '\0';
254 ioctl(-1, DM_VERSION, dm_arg);
255 printf("ioctl(-1, DM_VERSION, "
256 "{version=4.1.2, data_size=%u, flags=0}) = "
257 "-1 EBADF (%m)\n", 0xfacefeed);
260 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
261 dm_arg->flags = 0xffffffff;
262 ioctl(-1, DM_VERSION, dm_arg);
263 printf("ioctl(-1, DM_VERSION, "
264 "{version=4.1.2, data_size=%zu, "
265 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags="
266 "DM_READONLY_FLAG|DM_SUSPEND_FLAG|DM_EXISTS_FLAG|"
267 "DM_PERSISTENT_DEV_FLAG|DM_STATUS_TABLE_FLAG|"
268 "DM_ACTIVE_PRESENT_FLAG|DM_INACTIVE_PRESENT_FLAG|"
269 "DM_BUFFER_FULL_FLAG|DM_SKIP_BDGET_FLAG|DM_SKIP_LOCKFS_FLAG|"
270 "DM_NOFLUSH_FLAG|DM_QUERY_INACTIVE_TABLE_FLAG|"
271 "DM_UEVENT_GENERATED_FLAG|DM_UUID_FLAG|DM_SECURE_DATA_FLAG|"
272 "DM_DATA_OUT_FLAG|DM_DEFERRED_REMOVE|DM_INTERNAL_SUSPEND_FLAG|"
273 "0xfff80080}) = -1 EBADF (%m)\n",
274 min_sizeof_dm_ioctl);
277 init_s(&s.ioc, sizeof(s.ioc), 0);
278 ioctl(-1, DM_VERSION, &s);
279 printf("ioctl(-1, DM_VERSION, "
280 "{version=4.1.2, data_size=%zu, "
281 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0}) = "
282 "-1 EBADF (%m)\n", sizeof(s.ioc));
286 /* DM_LIST_DEVICES */
287 /* DM_LIST_VERSIONS */
288 for (i = 0; i < ARRAY_SIZE(dummy_check_cmds_nodev); i++) {
289 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
290 ioctl(-1, dummy_check_cmds_nodev[i].arg, dm_arg);
291 printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
292 "flags=0}) = -1 EBADF (%m)\n",
293 dummy_check_cmds_nodev[i].str,
295 dummy_check_cmds_nodev[i].has_params ?
296 ", data_start=0" : "");
306 /* DM_TABLE_STATUS */
307 for (i = 0; i < ARRAY_SIZE(dummy_check_cmds); i++) {
308 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
309 ioctl(-1, dummy_check_cmds[i].arg, dm_arg);
310 printf("ioctl(-1, %s, {version=4.1.2, data_size=%zu%s, "
311 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\"%s, "
312 "flags=0}) = -1 EBADF (%m)\n",
313 dummy_check_cmds[i].str, min_sizeof_dm_ioctl,
314 dummy_check_cmds[i].has_params ? ", data_start=0" : "",
315 dummy_check_cmds[i].has_event_nr ? ", event_nr=0" : "");
320 init_s(&s.ioc, sizeof(s.ioc), 0);
321 s.ioc.flags = DM_SUSPEND_FLAG;
322 s.ioc.event_nr = 0xbadc0ded;
323 ioctl(-1, DM_DEV_SUSPEND, &s);
324 printf("ioctl(-1, DM_DEV_SUSPEND, "
325 "{version=4.1.2, data_size=%zu, "
326 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
327 "flags=DM_SUSPEND_FLAG}) = -1 EBADF (%m)\n", sizeof(s.ioc));
329 init_s(&s.ioc, sizeof(s.ioc), 0);
330 s.ioc.event_nr = 0xbadc0ded;
331 ioctl(-1, DM_DEV_SUSPEND, &s);
332 printf("ioctl(-1, DM_DEV_SUSPEND, "
333 "{version=4.1.2, data_size=%zu, dev=makedev(18, 52), "
334 "name=\"nnn\", uuid=\"uuu\", event_nr=3134983661, "
335 "flags=0}) = -1 EBADF (%m)\n", sizeof(s.ioc));
339 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
340 s.ioc.target_count = 1;
341 s.u.ts.target_spec.sector_start = 0x10;
342 s.u.ts.target_spec.length = 0x20;
343 s.u.ts.target_spec.next =
344 sizeof(s.u.ts.target_spec) + sizeof(s.u.ts.target_params);
345 strcpy(s.u.ts.target_spec.target_type, "tgt");
346 strcpy(s.u.ts.target_params, "tparams");
347 ioctl(-1, DM_TABLE_LOAD, &s);
348 printf("ioctl(-1, DM_TABLE_LOAD, "
349 "{version=4.1.2, data_size=%u, data_start=%u, "
350 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
351 "target_count=1, flags=0, "
353 "{sector_start=16, length=32, target_type=\"tgt\", "
354 "string=\"tparams\"}"
355 # else /* !VERBOSE */
357 # endif /* VERBOSE */
358 "}) = -1 EBADF (%m)\n", s.ioc.data_size, s.ioc.data_start);
361 init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
362 dm_arg->data_size = sizeof(*dm_arg);
363 dm_arg->target_count = 0;
364 ioctl(-1, DM_TABLE_LOAD, dm_arg);
365 printf("ioctl(-1, DM_TABLE_LOAD, "
366 "{version=4.1.2, data_size=%zu, data_start=%zu, "
367 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
368 "target_count=0, flags=0}) = -1 EBADF (%m)\n",
369 sizeof(*dm_arg), min_sizeof_dm_ioctl);
371 /* Invalid data_start */
372 init_s(dm_arg, min_sizeof_dm_ioctl, 0xfffffff8);
373 dm_arg->data_size = sizeof(*dm_arg);
374 dm_arg->target_count = 1234;
375 ioctl(-1, DM_TABLE_LOAD, dm_arg);
376 printf("ioctl(-1, DM_TABLE_LOAD, "
377 "{version=4.1.2, data_size=%zu, data_start=%u, "
378 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
379 "target_count=1234, flags=0, "
381 "/* misplaced struct dm_target_spec */ ..."
382 # else /* !VERBOSE */
384 # endif /* VERBOSE */
385 "}) = -1 EBADF (%m)\n", sizeof(*dm_arg), 0xfffffff8);
387 /* Inaccessible pointer */
388 init_s(&dm_arg_open1->ioc, offsetof(struct dm_table_open_test, target1),
389 offsetof(struct dm_table_open_test, target1));
390 dm_arg_open1->ioc.data_size = sizeof(*dm_arg_open1);
391 dm_arg_open1->ioc.target_count = 0xdeaddea1;
392 ioctl(-1, DM_TABLE_LOAD, dm_arg_open1);
393 printf("ioctl(-1, DM_TABLE_LOAD, "
394 "{version=4.1.2, data_size=%zu, data_start=%zu, "
395 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
396 "target_count=3735936673, flags=0, "
399 # else /* !VERBOSE */
401 # endif /* VERBOSE */
402 "}) = -1 EBADF (%m)\n", sizeof(*dm_arg_open1),
403 offsetof(struct dm_table_open_test, target1)
405 , (char *) dm_arg_open1 +
406 offsetof(struct dm_table_open_test, target1)
407 # endif /* VERBOSE */
410 /* Inaccessible string */
411 init_s(&dm_arg_open2->ioc, offsetof(struct dm_table_open_test, param1),
412 offsetof(struct dm_table_open_test, target1));
413 dm_arg_open2->ioc.data_size = sizeof(*dm_arg_open2);
414 dm_arg_open2->ioc.target_count = 2;
415 init_dm_target_spec(&dm_arg_open2->target1, 7);
416 dm_arg_open2->target1.next =
417 offsetof(struct dm_table_open_test, target3) -
418 offsetof(struct dm_table_open_test, target1);
419 rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open2);
420 errstr = sprintrc(rc);
421 printf("ioctl(-1, DM_TABLE_LOAD, "
422 "{version=4.1.2, data_size=%zu, data_start=%zu, "
423 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
424 "target_count=2, flags=0, ",
425 sizeof(*dm_arg_open2),
426 offsetof(struct dm_table_open_test, target1));
428 print_dm_target_spec(&dm_arg_open2->target1, 7);
430 (char *) dm_arg_open2 +
431 offsetof(struct dm_table_open_test, param1),
432 (char *) dm_arg_open2 +
433 offsetof(struct dm_table_open_test, target3));
434 # else /* !VERBOSE */
436 # endif /* VERBOSE */
437 printf("}) = %s\n", errstr);
440 init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target5),
441 offsetof(struct dm_table_open_test, target0));
442 dm_arg_open3->ioc.target_count = 4;
444 init_dm_target_spec(&dm_arg_open3->target0, 9);
445 dm_arg_open3->target0.next =
446 offsetof(struct dm_table_open_test, target1) -
447 offsetof(struct dm_table_open_test, target0);
448 dm_arg_open3->param0[0] = '\0';
450 init_dm_target_spec(&dm_arg_open3->target1, 15);
451 dm_arg_open3->target1.next =
452 offsetof(struct dm_table_open_test, target3) -
453 offsetof(struct dm_table_open_test, target1);
454 dm_arg_open3->param1[0] = '\377';
455 dm_arg_open3->param1[1] = '\0';
457 init_dm_target_spec(&dm_arg_open3->target3, 42);
458 dm_arg_open3->target3.next = 0xdeadbeef;
459 dm_arg_open3->param3[0] = '\1';
460 dm_arg_open3->param3[1] = '\2';
461 dm_arg_open3->param3[2] = '\0';
463 rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
464 errstr = sprintrc(rc);
465 printf("ioctl(-1, DM_TABLE_LOAD, "
466 "{version=4.1.2, data_size=%zu, data_start=%zu, "
467 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
468 "target_count=4, flags=0, ",
469 offsetof(struct dm_table_open_test, target5),
470 offsetof(struct dm_table_open_test, target0));
472 print_dm_target_spec(&dm_arg_open3->target0, 9);
474 print_dm_target_spec(&dm_arg_open3->target1, 15);
475 printf("\"\\377\"}, ");
476 print_dm_target_spec(&dm_arg_open3->target1, 42);
477 printf("\"\\1\\2\"}, /* misplaced struct dm_target_spec */ ...");
478 # else /* !VERBOSE */
480 # endif /* VERBOSE */
481 printf("}) = %s\n", errstr);
483 #define FILL_DM_TARGET(id, id_next) \
485 init_dm_target_spec(&dm_arg_open3->target##id, id); \
486 dm_arg_open3->target##id.next = \
487 offsetof(struct dm_table_open_test, \
489 offsetof(struct dm_table_open_test, \
491 strncpy(dm_arg_open3->param##id, str129 + id * 2, id); \
492 dm_arg_open3->param##id[id] = '\0'; \
494 #define PRINT_DM_TARGET(id) \
496 print_dm_target_spec(&dm_arg_open3->target##id, id); \
497 printf("\"%.*s\"}, ", id, str129 + id * 2); \
500 /* max_strlen limit */
501 init_s(&dm_arg_open3->ioc, offsetof(struct dm_table_open_test, target9),
502 offsetof(struct dm_table_open_test, target0));
503 dm_arg_open3->ioc.data_size = sizeof(*dm_arg_open3);
504 dm_arg_open3->ioc.target_count = 0xbadc0ded;
505 FILL_DM_TARGET(0, 1);
506 FILL_DM_TARGET(1, 2);
507 FILL_DM_TARGET(2, 3);
508 FILL_DM_TARGET(3, 4);
509 FILL_DM_TARGET(4, 5);
510 FILL_DM_TARGET(5, 6);
511 FILL_DM_TARGET(6, 7);
512 FILL_DM_TARGET(7, 8);
513 FILL_DM_TARGET(8, 9);
514 rc = ioctl(-1, DM_TABLE_LOAD, dm_arg_open3);
515 errstr = sprintrc(rc);
516 printf("ioctl(-1, DM_TABLE_LOAD, "
517 "{version=4.1.2, data_size=%zu, data_start=%zu, "
518 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
519 "target_count=3134983661, flags=0, ",
520 sizeof(*dm_arg_open3),
521 offsetof(struct dm_table_open_test, target0));
532 # endif /* VERBOSE */
533 printf("...}) = %s\n", errstr);
537 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
538 s.u.tm.target_msg.sector = 0x1234;
539 strcpy(s.u.string + offsetof(struct dm_target_msg, message),
541 ioctl(-1, DM_TARGET_MSG, &s);
542 printf("ioctl(-1, DM_TARGET_MSG, "
543 "{version=4.1.2, data_size=%u, data_start=%u, "
544 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
546 "{sector=4660, message=\"long targ\"...}"
547 # else /* !VERBOSE */
549 # endif /* VERBOSE */
550 "}) = -1 EBADF (%m)\n",
551 s.ioc.data_size, s.ioc.data_start);
553 /* Invalid data_start */
554 init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
555 dm_arg->data_size = sizeof(*dm_arg);
556 ioctl(-1, DM_TARGET_MSG, dm_arg);
557 printf("ioctl(-1, DM_TARGET_MSG, "
558 "{version=4.1.2, data_size=%zu, data_start=%zu, "
559 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
561 "/* misplaced struct dm_target_msg */"
562 # else /* !VERBOSE */
564 # endif /* VERBOSE */
565 "}) = -1 EBADF (%m)\n",
566 sizeof(*dm_arg), min_sizeof_dm_ioctl);
568 /* Invalid data_start */
569 init_s(dm_arg, min_sizeof_dm_ioctl, 0xffffffff);
570 dm_arg->data_size = sizeof(*dm_arg);
571 ioctl(-1, DM_TARGET_MSG, dm_arg);
572 printf("ioctl(-1, DM_TARGET_MSG, "
573 "{version=4.1.2, data_size=%zu, data_start=%u, "
574 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
576 "/* misplaced struct dm_target_msg */"
577 # else /* !VERBOSE */
579 # endif /* VERBOSE */
580 "}) = -1 EBADF (%m)\n",
581 sizeof(*dm_arg), 0xffffffff);
583 /* Inaccessible pointer */
584 init_s(dm_arg, min_sizeof_dm_ioctl, 0);
585 dm_arg->data_size = sizeof(*dm_arg) + sizeof(struct dm_target_msg);
586 dm_arg->data_start = sizeof(*dm_arg);
587 ioctl(-1, DM_TARGET_MSG, dm_arg);
588 printf("ioctl(-1, DM_TARGET_MSG, "
589 "{version=4.1.2, data_size=%zu, data_start=%zu, "
590 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
593 # else /* !VERBOSE */
595 # endif /* VERBOSE */
596 "}) = -1 EBADF (%m)\n",
597 sizeof(*dm_arg) + sizeof(struct dm_target_msg),
600 , (char *) dm_arg + sizeof(*dm_arg)
601 # endif /* VERBOSE */
604 /* Inaccessible string */
605 init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
606 offsetof(struct dm_target_msg_test, msg));
607 dm_arg_msg->ioc.data_size = sizeof(*dm_arg_msg) + 1;
608 dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
609 rc = ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
610 errstr = sprintrc(rc);
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 sizeof(*dm_arg_msg) + 1,
615 offsetof(struct dm_target_msg_test, msg));
617 printf("{sector=%" PRI__u64 ", message=%p}",
618 (__u64) 0xdeadbeeffacef157ULL,
619 (char *) dm_arg_msg +
620 offsetof(struct dm_target_msg_test, msg.message));
621 # else /* !VERBOSE */
623 # endif /* VERBOSE */
624 printf("}) = %s\n", errstr);
626 /* Zero-sied string */
627 init_s(&dm_arg_msg->ioc, sizeof(*dm_arg_msg),
628 offsetof(struct dm_target_msg_test, msg));
629 dm_arg_msg->msg.sector = (__u64) 0xdeadbeeffacef157ULL;
630 rc = ioctl(-1, DM_TARGET_MSG, dm_arg_msg);
631 errstr = sprintrc(rc);
632 printf("ioctl(-1, DM_TARGET_MSG, "
633 "{version=4.1.2, data_size=%zu, data_start=%zu, "
634 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, ",
635 sizeof(*dm_arg_msg), offsetof(struct dm_target_msg_test, msg));
637 printf("{sector=%" PRI__u64 ", message=\"\"}",
638 (__u64) 0xdeadbeeffacef157ULL);
639 # else /* !VERBOSE */
641 # endif /* VERBOSE */
642 printf("}) = %s\n", errstr);
645 /* DM_DEV_SET_GEOMETRY */
646 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
647 strcpy(s.u.string, "10 20 30 40");
648 ioctl(-1, DM_DEV_SET_GEOMETRY, &s);
649 printf("ioctl(-1, DM_DEV_SET_GEOMETRY, "
650 "{version=4.1.2, data_size=%u, data_start=%u, "
651 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", flags=0, "
653 "string=\"10 20 30 \"..."
654 # else /* !VERBOSE */
656 # endif /* VERBOSE */
657 "}) = -1 EBADF (%m)\n",
658 s.ioc.data_size, s.ioc.data_start);
662 /* Inaccessible data */
663 init_s(dm_arg, min_sizeof_dm_ioctl, min_sizeof_dm_ioctl);
664 dm_arg->data_size = sizeof(*dm_arg);
665 memcpy(unaligned_dm_arg, dm_arg, offsetof(struct dm_ioctl, data));
666 ioctl(-1, DM_DEV_RENAME, unaligned_dm_arg);
667 printf("ioctl(-1, DM_DEV_RENAME, "
668 "{version=4.1.2, data_size=%zu, data_start=%zu, "
669 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
673 # else /* !VERBOSE */
675 # endif /* VERBOSE */
676 "}) = -1 EBADF (%m)\n",
677 sizeof(*unaligned_dm_arg), min_sizeof_dm_ioctl
679 , (char *) unaligned_dm_arg + min_sizeof_dm_ioctl
680 # endif /* VERBOSE */
683 /* Incorrect data_start data */
684 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
685 s.ioc.data_start = 0xdeadbeef;
686 ioctl(-1, DM_DEV_RENAME, &s);
687 printf("ioctl(-1, DM_DEV_RENAME, "
688 "{version=4.1.2, data_size=%u, data_start=3735928559, "
689 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
692 "/* misplaced string */"
693 # else /* !VERBOSE */
695 # endif /* VERBOSE */
696 "}) = -1 EBADF (%m)\n",
699 /* Strange but still valid data_start */
700 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
701 /* Curiously, this is a valid structure */
702 s.ioc.data_start = offsetof(struct dm_ioctl, name) + 1;
703 ioctl(-1, DM_DEV_RENAME, &s);
704 printf("ioctl(-1, DM_DEV_RENAME, "
705 "{version=4.1.2, data_size=%u, data_start=%zu, "
706 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
710 # else /* !VERBOSE */
712 # endif /* VERBOSE */
713 "}) = -1 EBADF (%m)\n",
715 offsetof(struct dm_ioctl, name) + 1);
718 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
719 strcpy(s.u.string, "new long name");
720 ioctl(-1, DM_DEV_RENAME, &s);
721 printf("ioctl(-1, DM_DEV_RENAME, "
722 "{version=4.1.2, data_size=%u, data_start=%u, "
723 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", event_nr=0, "
726 "string=\"new long \"..."
727 # else /* !VERBOSE */
729 # endif /* VERBOSE */
730 "}) = -1 EBADF (%m)\n",
731 s.ioc.data_size, s.ioc.data_start);
735 init_s(&s.ioc, sizeof(s), offsetof(struct s, u));
736 s.ioc.target_count = -1U;
737 ioctl(-1, DM_TABLE_LOAD, &s);
738 printf("ioctl(-1, DM_TABLE_LOAD, "
739 "{version=4.1.2, data_size=%u, data_start=%u, "
740 "dev=makedev(18, 52), name=\"nnn\", uuid=\"uuu\", "
741 "target_count=4294967295, flags=0, "
743 "{sector_start=0, length=0, target_type=\"\", string=\"\"}, "
744 "/* misplaced struct dm_target_spec */ "
745 # endif /* VERBOSE */
746 "...}) = -1 EBADF (%m)\n",
747 s.ioc.data_size, s.ioc.data_start);
749 puts("+++ exited with 0 +++");
753 #else /* !HAVE_LINUX_DM_IOCTL_H */
755 SKIP_MAIN_UNDEFINED("HAVE_LINUX_DM_IOCTL_H")
757 #endif /* HAVE_LINUX_DM_IOCTL_H */