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