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