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