1 /* 2 * Check decoding of DM_* commands of ioctl syscall. 3 * 4 * Copyright (c) 2016 Mikulas Patocka <mpatocka (at) redhat.com> 5 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr (at) gmail.com> 6 * Copyright (c) 2016-2018 The strace developers. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "tests.h" 33 34 #ifdef HAVE_LINUX_DM_IOCTL_H 35 36 # include <errno.h> 37 # include <inttypes.h> 38 # include <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 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 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 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 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