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