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