1 /*- 2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/bio.h> 37 #include <sys/sysctl.h> 38 #include <sys/malloc.h> 39 #include <sys/kthread.h> 40 #include <sys/proc.h> 41 #include <sys/sched.h> 42 #include <sys/uio.h> 43 44 #include <vm/uma.h> 45 46 #include <geom/geom.h> 47 #include <geom/eli/g_eli.h> 48 49 50 MALLOC_DECLARE(M_ELI); 51 52 53 static void 54 g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp) 55 { 56 struct g_eli_metadata md; 57 struct g_provider *pp; 58 const char *name; 59 u_char *key, mkey[G_ELI_DATAIVKEYLEN]; 60 int *nargs, *detach, *readonly; 61 int keysize, error; 62 u_int nkey; 63 64 g_topology_assert(); 65 66 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 67 if (nargs == NULL) { 68 gctl_error(req, "No '%s' argument.", "nargs"); 69 return; 70 } 71 if (*nargs != 1) { 72 gctl_error(req, "Invalid number of arguments."); 73 return; 74 } 75 76 detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 77 if (detach == NULL) { 78 gctl_error(req, "No '%s' argument.", "detach"); 79 return; 80 } 81 82 readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly)); 83 if (readonly == NULL) { 84 gctl_error(req, "No '%s' argument.", "readonly"); 85 return; 86 } 87 88 name = gctl_get_asciiparam(req, "arg0"); 89 if (name == NULL) { 90 gctl_error(req, "No 'arg%u' argument.", 0); 91 return; 92 } 93 if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 94 name += strlen("/dev/"); 95 pp = g_provider_by_name(name); 96 if (pp == NULL) { 97 gctl_error(req, "Provider %s is invalid.", name); 98 return; 99 } 100 error = g_eli_read_metadata(mp, pp, &md); 101 if (error != 0) { 102 gctl_error(req, "Cannot read metadata from %s (error=%d).", 103 name, error); 104 return; 105 } 106 if (md.md_keys == 0x00) { 107 bzero(&md, sizeof(md)); 108 gctl_error(req, "No valid keys on %s.", pp->name); 109 return; 110 } 111 112 key = gctl_get_param(req, "key", &keysize); 113 if (key == NULL || keysize != G_ELI_USERKEYLEN) { 114 bzero(&md, sizeof(md)); 115 gctl_error(req, "No '%s' argument.", "key"); 116 return; 117 } 118 119 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); 120 bzero(key, keysize); 121 if (error == -1) { 122 bzero(&md, sizeof(md)); 123 gctl_error(req, "Wrong key for %s.", pp->name); 124 return; 125 } else if (error > 0) { 126 bzero(&md, sizeof(md)); 127 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", 128 pp->name, error); 129 return; 130 } 131 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); 132 133 if (*detach && *readonly) { 134 bzero(&md, sizeof(md)); 135 gctl_error(req, "Options -d and -r are mutually exclusive."); 136 return; 137 } 138 if (*detach) 139 md.md_flags |= G_ELI_FLAG_WO_DETACH; 140 if (*readonly) 141 md.md_flags |= G_ELI_FLAG_RO; 142 g_eli_create(req, mp, pp, &md, mkey, nkey); 143 bzero(mkey, sizeof(mkey)); 144 bzero(&md, sizeof(md)); 145 } 146 147 static struct g_eli_softc * 148 g_eli_find_device(struct g_class *mp, const char *prov) 149 { 150 struct g_eli_softc *sc; 151 struct g_geom *gp; 152 struct g_provider *pp; 153 struct g_consumer *cp; 154 155 if (strncmp(prov, "/dev/", strlen("/dev/")) == 0) 156 prov += strlen("/dev/"); 157 LIST_FOREACH(gp, &mp->geom, geom) { 158 sc = gp->softc; 159 if (sc == NULL) 160 continue; 161 pp = LIST_FIRST(&gp->provider); 162 if (pp != NULL && strcmp(pp->name, prov) == 0) 163 return (sc); 164 cp = LIST_FIRST(&gp->consumer); 165 if (cp != NULL && cp->provider != NULL && 166 strcmp(cp->provider->name, prov) == 0) { 167 return (sc); 168 } 169 } 170 return (NULL); 171 } 172 173 static void 174 g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp) 175 { 176 struct g_eli_softc *sc; 177 int *force, *last, *nargs, error; 178 const char *prov; 179 char param[16]; 180 int i; 181 182 g_topology_assert(); 183 184 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 185 if (nargs == NULL) { 186 gctl_error(req, "No '%s' argument.", "nargs"); 187 return; 188 } 189 if (*nargs <= 0) { 190 gctl_error(req, "Missing device(s)."); 191 return; 192 } 193 force = gctl_get_paraml(req, "force", sizeof(*force)); 194 if (force == NULL) { 195 gctl_error(req, "No '%s' argument.", "force"); 196 return; 197 } 198 last = gctl_get_paraml(req, "last", sizeof(*last)); 199 if (last == NULL) { 200 gctl_error(req, "No '%s' argument.", "last"); 201 return; 202 } 203 204 for (i = 0; i < *nargs; i++) { 205 snprintf(param, sizeof(param), "arg%d", i); 206 prov = gctl_get_asciiparam(req, param); 207 if (prov == NULL) { 208 gctl_error(req, "No 'arg%d' argument.", i); 209 return; 210 } 211 sc = g_eli_find_device(mp, prov); 212 if (sc == NULL) { 213 gctl_error(req, "No such device: %s.", prov); 214 return; 215 } 216 if (*last) { 217 sc->sc_flags |= G_ELI_FLAG_RW_DETACH; 218 sc->sc_geom->access = g_eli_access; 219 } else { 220 error = g_eli_destroy(sc, *force); 221 if (error != 0) { 222 gctl_error(req, 223 "Cannot destroy device %s (error=%d).", 224 sc->sc_name, error); 225 return; 226 } 227 } 228 } 229 } 230 231 static void 232 g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) 233 { 234 struct g_eli_metadata md; 235 struct g_provider *pp; 236 const char *name; 237 intmax_t *keylen, *sectorsize; 238 u_char mkey[G_ELI_DATAIVKEYLEN]; 239 int *nargs, *detach; 240 241 g_topology_assert(); 242 bzero(&md, sizeof(md)); 243 244 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 245 if (nargs == NULL) { 246 gctl_error(req, "No '%s' argument.", "nargs"); 247 return; 248 } 249 if (*nargs != 1) { 250 gctl_error(req, "Invalid number of arguments."); 251 return; 252 } 253 254 detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 255 if (detach == NULL) { 256 gctl_error(req, "No '%s' argument.", "detach"); 257 return; 258 } 259 260 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 261 md.md_version = G_ELI_VERSION; 262 md.md_flags |= G_ELI_FLAG_ONETIME; 263 if (*detach) 264 md.md_flags |= G_ELI_FLAG_WO_DETACH; 265 266 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 267 name = gctl_get_asciiparam(req, "aalgo"); 268 if (name == NULL) { 269 gctl_error(req, "No '%s' argument.", "aalgo"); 270 return; 271 } 272 if (strcmp(name, "none") != 0) { 273 md.md_aalgo = g_eli_str2aalgo(name); 274 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 275 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 276 md.md_flags |= G_ELI_FLAG_AUTH; 277 } else { 278 /* 279 * For backward compatibility, check if the -a option 280 * was used to provide encryption algorithm. 281 */ 282 md.md_ealgo = g_eli_str2ealgo(name); 283 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 284 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 285 gctl_error(req, 286 "Invalid authentication algorithm."); 287 return; 288 } else { 289 gctl_error(req, "warning: The -e option, not " 290 "the -a option is now used to specify " 291 "encryption algorithm to use."); 292 } 293 } 294 } 295 296 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 297 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 298 name = gctl_get_asciiparam(req, "ealgo"); 299 if (name == NULL) { 300 gctl_error(req, "No '%s' argument.", "ealgo"); 301 return; 302 } 303 md.md_ealgo = g_eli_str2ealgo(name); 304 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 305 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 306 gctl_error(req, "Invalid encryption algorithm."); 307 return; 308 } 309 } 310 311 keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen)); 312 if (keylen == NULL) { 313 gctl_error(req, "No '%s' argument.", "keylen"); 314 return; 315 } 316 md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen); 317 if (md.md_keylen == 0) { 318 gctl_error(req, "Invalid '%s' argument.", "keylen"); 319 return; 320 } 321 322 /* Not important here. */ 323 md.md_provsize = 0; 324 /* Not important here. */ 325 bzero(md.md_salt, sizeof(md.md_salt)); 326 327 md.md_keys = 0x01; 328 arc4rand(mkey, sizeof(mkey), 0); 329 330 /* Not important here. */ 331 bzero(md.md_hash, sizeof(md.md_hash)); 332 333 name = gctl_get_asciiparam(req, "arg0"); 334 if (name == NULL) { 335 gctl_error(req, "No 'arg%u' argument.", 0); 336 return; 337 } 338 if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 339 name += strlen("/dev/"); 340 pp = g_provider_by_name(name); 341 if (pp == NULL) { 342 gctl_error(req, "Provider %s is invalid.", name); 343 return; 344 } 345 346 sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize)); 347 if (sectorsize == NULL) { 348 gctl_error(req, "No '%s' argument.", "sectorsize"); 349 return; 350 } 351 if (*sectorsize == 0) 352 md.md_sectorsize = pp->sectorsize; 353 else { 354 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) { 355 gctl_error(req, "Invalid sector size."); 356 return; 357 } 358 if (*sectorsize > PAGE_SIZE) { 359 gctl_error(req, "warning: Using sectorsize bigger than " 360 "the page size!"); 361 } 362 md.md_sectorsize = *sectorsize; 363 } 364 365 g_eli_create(req, mp, pp, &md, mkey, -1); 366 bzero(mkey, sizeof(mkey)); 367 bzero(&md, sizeof(md)); 368 } 369 370 static void 371 g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp) 372 { 373 struct g_eli_softc *sc; 374 struct g_eli_metadata md; 375 struct g_provider *pp; 376 struct g_consumer *cp; 377 char param[16]; 378 const char *prov; 379 u_char *sector; 380 int *nargs, *boot, *noboot; 381 int error; 382 u_int i; 383 384 g_topology_assert(); 385 386 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 387 if (nargs == NULL) { 388 gctl_error(req, "No '%s' argument.", "nargs"); 389 return; 390 } 391 if (*nargs <= 0) { 392 gctl_error(req, "Missing device(s)."); 393 return; 394 } 395 396 boot = gctl_get_paraml(req, "boot", sizeof(*boot)); 397 if (boot == NULL) { 398 gctl_error(req, "No '%s' argument.", "boot"); 399 return; 400 } 401 noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot)); 402 if (noboot == NULL) { 403 gctl_error(req, "No '%s' argument.", "noboot"); 404 return; 405 } 406 if (*boot && *noboot) { 407 gctl_error(req, "Options -b and -B are mutually exclusive."); 408 return; 409 } 410 if (!*boot && !*noboot) { 411 gctl_error(req, "No option given."); 412 return; 413 } 414 415 for (i = 0; i < *nargs; i++) { 416 snprintf(param, sizeof(param), "arg%d", i); 417 prov = gctl_get_asciiparam(req, param); 418 if (prov == NULL) { 419 gctl_error(req, "No 'arg%d' argument.", i); 420 return; 421 } 422 sc = g_eli_find_device(mp, prov); 423 if (sc == NULL) { 424 /* 425 * We ignore not attached providers, userland part will 426 * take care of them. 427 */ 428 G_ELI_DEBUG(1, "Skipping configuration of not attached " 429 "provider %s.", prov); 430 continue; 431 } 432 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) { 433 G_ELI_DEBUG(1, "BOOT flag already configured for %s.", 434 prov); 435 continue; 436 } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) { 437 G_ELI_DEBUG(1, "BOOT flag not configured for %s.", 438 prov); 439 continue; 440 } 441 if (sc->sc_flags & G_ELI_FLAG_RO) { 442 gctl_error(req, "Cannot change configuration of " 443 "read-only provider %s.", prov); 444 continue; 445 } 446 cp = LIST_FIRST(&sc->sc_geom->consumer); 447 pp = cp->provider; 448 error = g_eli_read_metadata(mp, pp, &md); 449 if (error != 0) { 450 gctl_error(req, 451 "Cannot read metadata from %s (error=%d).", 452 prov, error); 453 continue; 454 } 455 456 if (*boot) { 457 md.md_flags |= G_ELI_FLAG_BOOT; 458 sc->sc_flags |= G_ELI_FLAG_BOOT; 459 } else { 460 md.md_flags &= ~G_ELI_FLAG_BOOT; 461 sc->sc_flags &= ~G_ELI_FLAG_BOOT; 462 } 463 464 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 465 eli_metadata_encode(&md, sector); 466 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 467 pp->sectorsize); 468 if (error != 0) { 469 gctl_error(req, 470 "Cannot store metadata on %s (error=%d).", 471 prov, error); 472 } 473 bzero(&md, sizeof(md)); 474 bzero(sector, sizeof(sector)); 475 free(sector, M_ELI); 476 } 477 } 478 479 static void 480 g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) 481 { 482 struct g_eli_softc *sc; 483 struct g_eli_metadata md; 484 struct g_provider *pp; 485 struct g_consumer *cp; 486 const char *name; 487 u_char *key, *mkeydst, *sector; 488 intmax_t *valp; 489 int keysize, nkey, error; 490 491 g_topology_assert(); 492 493 name = gctl_get_asciiparam(req, "arg0"); 494 if (name == NULL) { 495 gctl_error(req, "No 'arg%u' argument.", 0); 496 return; 497 } 498 sc = g_eli_find_device(mp, name); 499 if (sc == NULL) { 500 gctl_error(req, "Provider %s is invalid.", name); 501 return; 502 } 503 if (sc->sc_flags & G_ELI_FLAG_RO) { 504 gctl_error(req, "Cannot change keys for read-only provider."); 505 return; 506 } 507 cp = LIST_FIRST(&sc->sc_geom->consumer); 508 pp = cp->provider; 509 510 error = g_eli_read_metadata(mp, pp, &md); 511 if (error != 0) { 512 gctl_error(req, "Cannot read metadata from %s (error=%d).", 513 name, error); 514 return; 515 } 516 517 valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 518 if (valp == NULL) { 519 gctl_error(req, "No '%s' argument.", "keyno"); 520 return; 521 } 522 if (*valp != -1) 523 nkey = *valp; 524 else 525 nkey = sc->sc_nkey; 526 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 527 gctl_error(req, "Invalid '%s' argument.", "keyno"); 528 return; 529 } 530 531 valp = gctl_get_paraml(req, "iterations", sizeof(*valp)); 532 if (valp == NULL) { 533 gctl_error(req, "No '%s' argument.", "iterations"); 534 return; 535 } 536 /* Check if iterations number should and can be changed. */ 537 if (*valp != -1) { 538 if (bitcount32(md.md_keys) != 1) { 539 gctl_error(req, "To be able to use '-i' option, only " 540 "one key can be defined."); 541 return; 542 } 543 if (md.md_keys != (1 << nkey)) { 544 gctl_error(req, "Only already defined key can be " 545 "changed when '-i' option is used."); 546 return; 547 } 548 md.md_iterations = *valp; 549 } 550 551 key = gctl_get_param(req, "key", &keysize); 552 if (key == NULL || keysize != G_ELI_USERKEYLEN) { 553 bzero(&md, sizeof(md)); 554 gctl_error(req, "No '%s' argument.", "key"); 555 return; 556 } 557 558 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 559 md.md_keys |= (1 << nkey); 560 561 bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey)); 562 563 /* Encrypt Master Key with the new key. */ 564 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst); 565 bzero(key, sizeof(key)); 566 if (error != 0) { 567 bzero(&md, sizeof(md)); 568 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); 569 return; 570 } 571 572 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 573 /* Store metadata with fresh key. */ 574 eli_metadata_encode(&md, sector); 575 bzero(&md, sizeof(md)); 576 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 577 pp->sectorsize); 578 bzero(sector, sizeof(sector)); 579 free(sector, M_ELI); 580 if (error != 0) { 581 gctl_error(req, "Cannot store metadata on %s (error=%d).", 582 pp->name, error); 583 return; 584 } 585 G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name); 586 } 587 588 static void 589 g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp) 590 { 591 struct g_eli_softc *sc; 592 struct g_eli_metadata md; 593 struct g_provider *pp; 594 struct g_consumer *cp; 595 const char *name; 596 u_char *mkeydst, *sector; 597 intmax_t *valp; 598 size_t keysize; 599 int error, nkey, *all, *force; 600 u_int i; 601 602 g_topology_assert(); 603 604 nkey = 0; /* fixes causeless gcc warning */ 605 606 name = gctl_get_asciiparam(req, "arg0"); 607 if (name == NULL) { 608 gctl_error(req, "No 'arg%u' argument.", 0); 609 return; 610 } 611 sc = g_eli_find_device(mp, name); 612 if (sc == NULL) { 613 gctl_error(req, "Provider %s is invalid.", name); 614 return; 615 } 616 if (sc->sc_flags & G_ELI_FLAG_RO) { 617 gctl_error(req, "Cannot delete keys for read-only provider."); 618 return; 619 } 620 cp = LIST_FIRST(&sc->sc_geom->consumer); 621 pp = cp->provider; 622 623 error = g_eli_read_metadata(mp, pp, &md); 624 if (error != 0) { 625 gctl_error(req, "Cannot read metadata from %s (error=%d).", 626 name, error); 627 return; 628 } 629 630 all = gctl_get_paraml(req, "all", sizeof(*all)); 631 if (all == NULL) { 632 gctl_error(req, "No '%s' argument.", "all"); 633 return; 634 } 635 636 if (*all) { 637 mkeydst = md.md_mkeys; 638 keysize = sizeof(md.md_mkeys); 639 } else { 640 force = gctl_get_paraml(req, "force", sizeof(*force)); 641 if (force == NULL) { 642 gctl_error(req, "No '%s' argument.", "force"); 643 return; 644 } 645 646 valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 647 if (valp == NULL) { 648 gctl_error(req, "No '%s' argument.", "keyno"); 649 return; 650 } 651 if (*valp != -1) 652 nkey = *valp; 653 else 654 nkey = sc->sc_nkey; 655 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 656 gctl_error(req, "Invalid '%s' argument.", "keyno"); 657 return; 658 } 659 if (!(md.md_keys & (1 << nkey)) && !*force) { 660 gctl_error(req, "Master Key %u is not set.", nkey); 661 return; 662 } 663 md.md_keys &= ~(1 << nkey); 664 if (md.md_keys == 0 && !*force) { 665 gctl_error(req, "This is the last Master Key. Use '-f' " 666 "flag if you really want to remove it."); 667 return; 668 } 669 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 670 keysize = G_ELI_MKEYLEN; 671 } 672 673 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 674 for (i = 0; i <= g_eli_overwrites; i++) { 675 if (i == g_eli_overwrites) 676 bzero(mkeydst, keysize); 677 else 678 arc4rand(mkeydst, keysize, 0); 679 /* Store metadata with destroyed key. */ 680 eli_metadata_encode(&md, sector); 681 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 682 pp->sectorsize); 683 if (error != 0) { 684 G_ELI_DEBUG(0, "Cannot store metadata on %s " 685 "(error=%d).", pp->name, error); 686 } 687 /* 688 * Flush write cache so we don't overwrite data N times in cache 689 * and only once on disk. 690 */ 691 g_io_flush(cp); 692 } 693 bzero(&md, sizeof(md)); 694 bzero(sector, sizeof(sector)); 695 free(sector, M_ELI); 696 if (*all) 697 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); 698 else 699 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name); 700 } 701 702 static int 703 g_eli_kill_one(struct g_eli_softc *sc) 704 { 705 struct g_provider *pp; 706 struct g_consumer *cp; 707 int error = 0; 708 709 g_topology_assert(); 710 711 if (sc == NULL) 712 return (ENOENT); 713 714 pp = LIST_FIRST(&sc->sc_geom->provider); 715 g_error_provider(pp, ENXIO); 716 717 cp = LIST_FIRST(&sc->sc_geom->consumer); 718 pp = cp->provider; 719 720 if (sc->sc_flags & G_ELI_FLAG_RO) { 721 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only " 722 "provider: %s.", pp->name); 723 } else { 724 u_char *sector; 725 u_int i; 726 int err; 727 728 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK); 729 for (i = 0; i <= g_eli_overwrites; i++) { 730 if (i == g_eli_overwrites) 731 bzero(sector, pp->sectorsize); 732 else 733 arc4rand(sector, pp->sectorsize, 0); 734 err = g_write_data(cp, pp->mediasize - pp->sectorsize, 735 sector, pp->sectorsize); 736 if (err != 0) { 737 G_ELI_DEBUG(0, "Cannot erase metadata on %s " 738 "(error=%d).", pp->name, err); 739 if (error == 0) 740 error = err; 741 } 742 } 743 free(sector, M_ELI); 744 } 745 if (error == 0) 746 G_ELI_DEBUG(0, "%s has been killed.", pp->name); 747 g_eli_destroy(sc, 1); 748 return (error); 749 } 750 751 static void 752 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp) 753 { 754 int *all, *nargs; 755 int error; 756 757 g_topology_assert(); 758 759 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 760 if (nargs == NULL) { 761 gctl_error(req, "No '%s' argument.", "nargs"); 762 return; 763 } 764 all = gctl_get_paraml(req, "all", sizeof(*all)); 765 if (all == NULL) { 766 gctl_error(req, "No '%s' argument.", "all"); 767 return; 768 } 769 if (!*all && *nargs == 0) { 770 gctl_error(req, "Too few arguments."); 771 return; 772 } 773 774 if (*all) { 775 struct g_geom *gp, *gp2; 776 777 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 778 error = g_eli_kill_one(gp->softc); 779 if (error != 0) 780 gctl_error(req, "Not fully done."); 781 } 782 } else { 783 struct g_eli_softc *sc; 784 const char *prov; 785 char param[16]; 786 int i; 787 788 for (i = 0; i < *nargs; i++) { 789 snprintf(param, sizeof(param), "arg%d", i); 790 prov = gctl_get_asciiparam(req, param); 791 if (prov == NULL) { 792 G_ELI_DEBUG(0, "No 'arg%d' argument.", i); 793 continue; 794 } 795 796 sc = g_eli_find_device(mp, prov); 797 if (sc == NULL) { 798 G_ELI_DEBUG(0, "No such provider: %s.", prov); 799 continue; 800 } 801 error = g_eli_kill_one(sc); 802 if (error != 0) 803 gctl_error(req, "Not fully done."); 804 } 805 } 806 } 807 808 void 809 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) 810 { 811 uint32_t *version; 812 813 g_topology_assert(); 814 815 version = gctl_get_paraml(req, "version", sizeof(*version)); 816 if (version == NULL) { 817 gctl_error(req, "No '%s' argument.", "version"); 818 return; 819 } 820 if (*version != G_ELI_VERSION) { 821 gctl_error(req, "Userland and kernel parts are out of sync."); 822 return; 823 } 824 825 if (strcmp(verb, "attach") == 0) 826 g_eli_ctl_attach(req, mp); 827 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0) 828 g_eli_ctl_detach(req, mp); 829 else if (strcmp(verb, "onetime") == 0) 830 g_eli_ctl_onetime(req, mp); 831 else if (strcmp(verb, "configure") == 0) 832 g_eli_ctl_configure(req, mp); 833 else if (strcmp(verb, "setkey") == 0) 834 g_eli_ctl_setkey(req, mp); 835 else if (strcmp(verb, "delkey") == 0) 836 g_eli_ctl_delkey(req, mp); 837 else if (strcmp(verb, "kill") == 0) 838 g_eli_ctl_kill(req, mp); 839 else 840 gctl_error(req, "Unknown verb."); 841 } 842