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 57static const char str129[] = STR32 STR32 STR32 STR32 "6"; 58 59static const __u64 dts_sector_base = (__u64) 0xdeadca75facef157ULL; 60static const __u64 dts_sector_step = (__u64) 0x100000001ULL; 61static const __u64 dts_length_base = (__u64) 0xbadc0dedda7a1057ULL; 62static const __u64 dts_length_step = (__u64) 0x700000007ULL; 63static const __s32 dts_status_base = (__s32) 3141592653U; 64static const __s32 dts_status_step = 0x1234; 65 66static const size_t min_sizeof_dm_ioctl = 67 offsetof(struct dm_ioctl, data); 68 69static 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 84struct 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 108struct dm_target_msg_test { 109 struct dm_ioctl ioc; 110 struct dm_target_msg msg; 111}; 112 113struct args { 114 unsigned int arg; 115 const char *str; 116 bool has_params; 117 bool has_event_nr; 118}; 119 120 121static void 122init_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 135static void 136init_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 150static void 151print_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 162int 163main(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 775SKIP_MAIN_UNDEFINED("HAVE_LINUX_DM_IOCTL_H") 776 777#endif /* HAVE_LINUX_DM_IOCTL_H */ 778