The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/eli/g_eli_ctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
    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: releng/11.2/sys/geom/eli/g_eli_ctl.c 329114 2018-02-11 02:27:50Z kevans $");
   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 ? TRUE : FALSE);
  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, *notrim;
  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         strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
  255         md.md_version = G_ELI_VERSION;
  256         md.md_flags |= G_ELI_FLAG_ONETIME;
  257 
  258         detach = gctl_get_paraml(req, "detach", sizeof(*detach));
  259         if (detach != NULL && *detach)
  260                 md.md_flags |= G_ELI_FLAG_WO_DETACH;
  261         notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
  262         if (notrim != NULL && *notrim)
  263                 md.md_flags |= G_ELI_FLAG_NODELETE;
  264 
  265         md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
  266         name = gctl_get_asciiparam(req, "aalgo");
  267         if (name == NULL) {
  268                 gctl_error(req, "No '%s' argument.", "aalgo");
  269                 return;
  270         }
  271         if (*name != '\0') {
  272                 md.md_aalgo = g_eli_str2aalgo(name);
  273                 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
  274                     md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
  275                         md.md_flags |= G_ELI_FLAG_AUTH;
  276                 } else {
  277                         /*
  278                          * For backward compatibility, check if the -a option
  279                          * was used to provide encryption algorithm.
  280                          */
  281                         md.md_ealgo = g_eli_str2ealgo(name);
  282                         if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
  283                             md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
  284                                 gctl_error(req,
  285                                     "Invalid authentication algorithm.");
  286                                 return;
  287                         } else {
  288                                 gctl_error(req, "warning: The -e option, not "
  289                                     "the -a option is now used to specify "
  290                                     "encryption algorithm to use.");
  291                         }
  292                 }
  293         }
  294 
  295         if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
  296             md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
  297                 name = gctl_get_asciiparam(req, "ealgo");
  298                 if (name == NULL) {
  299                         gctl_error(req, "No '%s' argument.", "ealgo");
  300                         return;
  301                 }
  302                 md.md_ealgo = g_eli_str2ealgo(name);
  303                 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
  304                     md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
  305                         gctl_error(req, "Invalid encryption algorithm.");
  306                         return;
  307                 }
  308         }
  309 
  310         keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
  311         if (keylen == NULL) {
  312                 gctl_error(req, "No '%s' argument.", "keylen");
  313                 return;
  314         }
  315         md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
  316         if (md.md_keylen == 0) {
  317                 gctl_error(req, "Invalid '%s' argument.", "keylen");
  318                 return;
  319         }
  320 
  321         /* Not important here. */
  322         md.md_provsize = 0;
  323         /* Not important here. */
  324         bzero(md.md_salt, sizeof(md.md_salt));
  325 
  326         md.md_keys = 0x01;
  327         arc4rand(mkey, sizeof(mkey), 0);
  328 
  329         /* Not important here. */
  330         bzero(md.md_hash, sizeof(md.md_hash));
  331 
  332         name = gctl_get_asciiparam(req, "arg0");
  333         if (name == NULL) {
  334                 gctl_error(req, "No 'arg%u' argument.", 0);
  335                 return;
  336         }
  337         if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
  338                 name += strlen("/dev/");
  339         pp = g_provider_by_name(name);
  340         if (pp == NULL) {
  341                 gctl_error(req, "Provider %s is invalid.", name);
  342                 return;
  343         }
  344 
  345         sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
  346         if (sectorsize == NULL) {
  347                 gctl_error(req, "No '%s' argument.", "sectorsize");
  348                 return;
  349         }
  350         if (*sectorsize == 0)
  351                 md.md_sectorsize = pp->sectorsize;
  352         else {
  353                 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
  354                         gctl_error(req, "Invalid sector size.");
  355                         return;
  356                 }
  357                 if (*sectorsize > PAGE_SIZE) {
  358                         gctl_error(req, "warning: Using sectorsize bigger than "
  359                             "the page size!");
  360                 }
  361                 md.md_sectorsize = *sectorsize;
  362         }
  363 
  364         g_eli_create(req, mp, pp, &md, mkey, -1);
  365         bzero(mkey, sizeof(mkey));
  366         bzero(&md, sizeof(md));
  367 }
  368 
  369 static void
  370 g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
  371 {
  372         struct g_eli_softc *sc;
  373         struct g_eli_metadata md;
  374         struct g_provider *pp;
  375         struct g_consumer *cp;
  376         char param[16];
  377         const char *prov;
  378         u_char *sector;
  379         int *nargs, *boot, *noboot, *trim, *notrim, *geliboot, *nogeliboot;
  380         int *displaypass, *nodisplaypass;
  381         int zero, error, changed;
  382         u_int i;
  383 
  384         g_topology_assert();
  385 
  386         changed = 0;
  387         zero = 0;
  388 
  389         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  390         if (nargs == NULL) {
  391                 gctl_error(req, "No '%s' argument.", "nargs");
  392                 return;
  393         }
  394         if (*nargs <= 0) {
  395                 gctl_error(req, "Missing device(s).");
  396                 return;
  397         }
  398 
  399         boot = gctl_get_paraml(req, "boot", sizeof(*boot));
  400         if (boot == NULL)
  401                 boot = &zero;
  402         noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
  403         if (noboot == NULL)
  404                 noboot = &zero;
  405         if (*boot && *noboot) {
  406                 gctl_error(req, "Options -b and -B are mutually exclusive.");
  407                 return;
  408         }
  409         if (*boot || *noboot)
  410                 changed = 1;
  411 
  412         trim = gctl_get_paraml(req, "trim", sizeof(*trim));
  413         if (trim == NULL)
  414                 trim = &zero;
  415         notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
  416         if (notrim == NULL)
  417                 notrim = &zero;
  418         if (*trim && *notrim) {
  419                 gctl_error(req, "Options -t and -T are mutually exclusive.");
  420                 return;
  421         }
  422         if (*trim || *notrim)
  423                 changed = 1;
  424 
  425         geliboot = gctl_get_paraml(req, "geliboot", sizeof(*geliboot));
  426         if (geliboot == NULL)
  427                 geliboot = &zero;
  428         nogeliboot = gctl_get_paraml(req, "nogeliboot", sizeof(*nogeliboot));
  429         if (nogeliboot == NULL)
  430                 nogeliboot = &zero;
  431         if (*geliboot && *nogeliboot) {
  432                 gctl_error(req, "Options -g and -G are mutually exclusive.");
  433                 return;
  434         }
  435         if (*geliboot || *nogeliboot)
  436                 changed = 1;
  437 
  438         displaypass = gctl_get_paraml(req, "displaypass", sizeof(*displaypass));
  439         if (displaypass == NULL)
  440                 displaypass = &zero;
  441         nodisplaypass = gctl_get_paraml(req, "nodisplaypass", sizeof(*nodisplaypass));
  442         if (nodisplaypass == NULL)
  443                 nodisplaypass = &zero;
  444         if (*displaypass && *nodisplaypass) {
  445                 gctl_error(req, "Options -d and -D are mutually exclusive.");
  446                 return;
  447         }
  448         if (*displaypass || *nodisplaypass)
  449                 changed = 1;
  450 
  451         if (!changed) {
  452                 gctl_error(req, "No option given.");
  453                 return;
  454         }
  455 
  456         for (i = 0; i < *nargs; i++) {
  457                 snprintf(param, sizeof(param), "arg%d", i);
  458                 prov = gctl_get_asciiparam(req, param);
  459                 if (prov == NULL) {
  460                         gctl_error(req, "No 'arg%d' argument.", i);
  461                         return;
  462                 }
  463                 sc = g_eli_find_device(mp, prov);
  464                 if (sc == NULL) {
  465                         /*
  466                          * We ignore not attached providers, userland part will
  467                          * take care of them.
  468                          */
  469                         G_ELI_DEBUG(1, "Skipping configuration of not attached "
  470                             "provider %s.", prov);
  471                         continue;
  472                 }
  473                 if (sc->sc_flags & G_ELI_FLAG_RO) {
  474                         gctl_error(req, "Cannot change configuration of "
  475                             "read-only provider %s.", prov);
  476                         continue;
  477                 }
  478 
  479                 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
  480                         G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
  481                             prov);
  482                         continue;
  483                 } else if (*noboot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
  484                         G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
  485                             prov);
  486                         continue;
  487                 }
  488 
  489                 if (*notrim && (sc->sc_flags & G_ELI_FLAG_NODELETE)) {
  490                         G_ELI_DEBUG(1, "TRIM disable flag already configured for %s.",
  491                             prov);
  492                         continue;
  493                 } else if (*trim && !(sc->sc_flags & G_ELI_FLAG_NODELETE)) {
  494                         G_ELI_DEBUG(1, "TRIM disable flag not configured for %s.",
  495                             prov);
  496                         continue;
  497                 }
  498 
  499                 if (*geliboot && (sc->sc_flags & G_ELI_FLAG_GELIBOOT)) {
  500                         G_ELI_DEBUG(1, "GELIBOOT flag already configured for %s.",
  501                             prov);
  502                         continue;
  503                 } else if (*nogeliboot && !(sc->sc_flags & G_ELI_FLAG_GELIBOOT)) {
  504                         G_ELI_DEBUG(1, "GELIBOOT flag not configured for %s.",
  505                             prov);
  506                         continue;
  507                 }
  508 
  509                 if (*displaypass && (sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
  510                         G_ELI_DEBUG(1, "GELIDISPLAYPASS flag already configured for %s.",
  511                             prov);
  512                         continue;
  513                 } else if (*nodisplaypass &&
  514                     !(sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
  515                         G_ELI_DEBUG(1, "GELIDISPLAYPASS flag not configured for %s.",
  516                             prov);
  517                         continue;
  518                 }
  519 
  520                 if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
  521                         /*
  522                          * ONETIME providers don't write metadata to
  523                          * disk, so don't try reading it.  This means
  524                          * we're bit-flipping uninitialized memory in md
  525                          * below, but that's OK; we don't do anything
  526                          * with it later.
  527                          */
  528                         cp = LIST_FIRST(&sc->sc_geom->consumer);
  529                         pp = cp->provider;
  530                         error = g_eli_read_metadata(mp, pp, &md);
  531                         if (error != 0) {
  532                             gctl_error(req,
  533                                 "Cannot read metadata from %s (error=%d).",
  534                                 prov, error);
  535                             continue;
  536                         }
  537                 }
  538 
  539                 if (*boot) {
  540                         md.md_flags |= G_ELI_FLAG_BOOT;
  541                         sc->sc_flags |= G_ELI_FLAG_BOOT;
  542                 } else if (*noboot) {
  543                         md.md_flags &= ~G_ELI_FLAG_BOOT;
  544                         sc->sc_flags &= ~G_ELI_FLAG_BOOT;
  545                 }
  546 
  547                 if (*notrim) {
  548                         md.md_flags |= G_ELI_FLAG_NODELETE;
  549                         sc->sc_flags |= G_ELI_FLAG_NODELETE;
  550                 } else if (*trim) {
  551                         md.md_flags &= ~G_ELI_FLAG_NODELETE;
  552                         sc->sc_flags &= ~G_ELI_FLAG_NODELETE;
  553                 }
  554 
  555                 if (*geliboot) {
  556                         md.md_flags |= G_ELI_FLAG_GELIBOOT;
  557                         sc->sc_flags |= G_ELI_FLAG_GELIBOOT;
  558                 } else if (*nogeliboot) {
  559                         md.md_flags &= ~G_ELI_FLAG_GELIBOOT;
  560                         sc->sc_flags &= ~G_ELI_FLAG_GELIBOOT;
  561                 }
  562 
  563                 if (*displaypass) {
  564                         md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
  565                         sc->sc_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
  566                 } else if (*nodisplaypass) {
  567                         md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
  568                         sc->sc_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
  569                 }
  570 
  571                 if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
  572                         /* There's no metadata on disk so we are done here. */
  573                         continue;
  574                 }
  575 
  576                 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  577                 eli_metadata_encode(&md, sector);
  578                 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  579                     pp->sectorsize);
  580                 if (error != 0) {
  581                         gctl_error(req,
  582                             "Cannot store metadata on %s (error=%d).",
  583                             prov, error);
  584                 }
  585                 bzero(&md, sizeof(md));
  586                 bzero(sector, pp->sectorsize);
  587                 free(sector, M_ELI);
  588         }
  589 }
  590 
  591 static void
  592 g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
  593 {
  594         struct g_eli_softc *sc;
  595         struct g_eli_metadata md;
  596         struct g_provider *pp;
  597         struct g_consumer *cp;
  598         const char *name;
  599         u_char *key, *mkeydst, *sector;
  600         intmax_t *valp;
  601         int keysize, nkey, error;
  602 
  603         g_topology_assert();
  604 
  605         name = gctl_get_asciiparam(req, "arg0");
  606         if (name == NULL) {
  607                 gctl_error(req, "No 'arg%u' argument.", 0);
  608                 return;
  609         }
  610         sc = g_eli_find_device(mp, name);
  611         if (sc == NULL) {
  612                 gctl_error(req, "Provider %s is invalid.", name);
  613                 return;
  614         }
  615         if (sc->sc_flags & G_ELI_FLAG_RO) {
  616                 gctl_error(req, "Cannot change keys for read-only provider.");
  617                 return;
  618         }
  619         cp = LIST_FIRST(&sc->sc_geom->consumer);
  620         pp = cp->provider;
  621 
  622         error = g_eli_read_metadata(mp, pp, &md);
  623         if (error != 0) {
  624                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
  625                     name, error);
  626                 return;
  627         }
  628 
  629         valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
  630         if (valp == NULL) {
  631                 gctl_error(req, "No '%s' argument.", "keyno");
  632                 return;
  633         }
  634         if (*valp != -1)
  635                 nkey = *valp;
  636         else
  637                 nkey = sc->sc_nkey;
  638         if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
  639                 gctl_error(req, "Invalid '%s' argument.", "keyno");
  640                 return;
  641         }
  642 
  643         valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
  644         if (valp == NULL) {
  645                 gctl_error(req, "No '%s' argument.", "iterations");
  646                 return;
  647         }
  648         /* Check if iterations number should and can be changed. */
  649         if (*valp != -1 && md.md_iterations == -1) {
  650                 md.md_iterations = *valp;
  651         } else if (*valp != -1 && *valp != md.md_iterations) {
  652                 if (bitcount32(md.md_keys) != 1) {
  653                         gctl_error(req, "To be able to use '-i' option, only "
  654                             "one key can be defined.");
  655                         return;
  656                 }
  657                 if (md.md_keys != (1 << nkey)) {
  658                         gctl_error(req, "Only already defined key can be "
  659                             "changed when '-i' option is used.");
  660                         return;
  661                 }
  662                 md.md_iterations = *valp;
  663         }
  664 
  665         key = gctl_get_param(req, "key", &keysize);
  666         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
  667                 bzero(&md, sizeof(md));
  668                 gctl_error(req, "No '%s' argument.", "key");
  669                 return;
  670         }
  671 
  672         mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
  673         md.md_keys |= (1 << nkey);
  674 
  675         bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
  676 
  677         /* Encrypt Master Key with the new key. */
  678         error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
  679         bzero(key, keysize);
  680         if (error != 0) {
  681                 bzero(&md, sizeof(md));
  682                 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
  683                 return;
  684         }
  685 
  686         sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  687         /* Store metadata with fresh key. */
  688         eli_metadata_encode(&md, sector);
  689         bzero(&md, sizeof(md));
  690         error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  691             pp->sectorsize);
  692         bzero(sector, pp->sectorsize);
  693         free(sector, M_ELI);
  694         if (error != 0) {
  695                 gctl_error(req, "Cannot store metadata on %s (error=%d).",
  696                     pp->name, error);
  697                 return;
  698         }
  699         G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
  700 }
  701 
  702 static void
  703 g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
  704 {
  705         struct g_eli_softc *sc;
  706         struct g_eli_metadata md;
  707         struct g_provider *pp;
  708         struct g_consumer *cp;
  709         const char *name;
  710         u_char *mkeydst, *sector;
  711         intmax_t *valp;
  712         size_t keysize;
  713         int error, nkey, *all, *force;
  714         u_int i;
  715 
  716         g_topology_assert();
  717 
  718         nkey = 0;       /* fixes causeless gcc warning */
  719 
  720         name = gctl_get_asciiparam(req, "arg0");
  721         if (name == NULL) {
  722                 gctl_error(req, "No 'arg%u' argument.", 0);
  723                 return;
  724         }
  725         sc = g_eli_find_device(mp, name);
  726         if (sc == NULL) {
  727                 gctl_error(req, "Provider %s is invalid.", name);
  728                 return;
  729         }
  730         if (sc->sc_flags & G_ELI_FLAG_RO) {
  731                 gctl_error(req, "Cannot delete keys for read-only provider.");
  732                 return;
  733         }
  734         cp = LIST_FIRST(&sc->sc_geom->consumer);
  735         pp = cp->provider;
  736 
  737         error = g_eli_read_metadata(mp, pp, &md);
  738         if (error != 0) {
  739                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
  740                     name, error);
  741                 return;
  742         }
  743 
  744         all = gctl_get_paraml(req, "all", sizeof(*all));
  745         if (all == NULL) {
  746                 gctl_error(req, "No '%s' argument.", "all");
  747                 return;
  748         }
  749 
  750         if (*all) {
  751                 mkeydst = md.md_mkeys;
  752                 keysize = sizeof(md.md_mkeys);
  753         } else {
  754                 force = gctl_get_paraml(req, "force", sizeof(*force));
  755                 if (force == NULL) {
  756                         gctl_error(req, "No '%s' argument.", "force");
  757                         return;
  758                 }
  759 
  760                 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
  761                 if (valp == NULL) {
  762                         gctl_error(req, "No '%s' argument.", "keyno");
  763                         return;
  764                 }
  765                 if (*valp != -1)
  766                         nkey = *valp;
  767                 else
  768                         nkey = sc->sc_nkey;
  769                 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
  770                         gctl_error(req, "Invalid '%s' argument.", "keyno");
  771                         return;
  772                 }
  773                 if (!(md.md_keys & (1 << nkey)) && !*force) {
  774                         gctl_error(req, "Master Key %u is not set.", nkey);
  775                         return;
  776                 }
  777                 md.md_keys &= ~(1 << nkey);
  778                 if (md.md_keys == 0 && !*force) {
  779                         gctl_error(req, "This is the last Master Key. Use '-f' "
  780                             "flag if you really want to remove it.");
  781                         return;
  782                 }
  783                 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
  784                 keysize = G_ELI_MKEYLEN;
  785         }
  786 
  787         sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  788         for (i = 0; i <= g_eli_overwrites; i++) {
  789                 if (i == g_eli_overwrites)
  790                         bzero(mkeydst, keysize);
  791                 else
  792                         arc4rand(mkeydst, keysize, 0);
  793                 /* Store metadata with destroyed key. */
  794                 eli_metadata_encode(&md, sector);
  795                 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  796                     pp->sectorsize);
  797                 if (error != 0) {
  798                         G_ELI_DEBUG(0, "Cannot store metadata on %s "
  799                             "(error=%d).", pp->name, error);
  800                 }
  801                 /*
  802                  * Flush write cache so we don't overwrite data N times in cache
  803                  * and only once on disk.
  804                  */
  805                 (void)g_io_flush(cp);
  806         }
  807         bzero(&md, sizeof(md));
  808         bzero(sector, pp->sectorsize);
  809         free(sector, M_ELI);
  810         if (*all)
  811                 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
  812         else
  813                 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
  814 }
  815 
  816 static void
  817 g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_req *req)
  818 {
  819         struct g_eli_worker *wr;
  820 
  821         g_topology_assert();
  822 
  823         KASSERT(sc != NULL, ("NULL sc"));
  824 
  825         if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
  826                 gctl_error(req,
  827                     "Device %s is using one-time key, suspend not supported.",
  828                     sc->sc_name);
  829                 return;
  830         }
  831 
  832         mtx_lock(&sc->sc_queue_mtx);
  833         if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
  834                 mtx_unlock(&sc->sc_queue_mtx);
  835                 gctl_error(req, "Device %s already suspended.",
  836                     sc->sc_name);
  837                 return;
  838         }
  839         sc->sc_flags |= G_ELI_FLAG_SUSPEND;
  840         wakeup(sc);
  841         for (;;) {
  842                 LIST_FOREACH(wr, &sc->sc_workers, w_next) {
  843                         if (wr->w_active)
  844                                 break;
  845                 }
  846                 if (wr == NULL)
  847                         break;
  848                 /* Not all threads suspended. */
  849                 msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
  850                     "geli:suspend", 0);
  851         }
  852         /*
  853          * Clear sensitive data on suspend, they will be recovered on resume.
  854          */
  855         bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
  856         g_eli_key_destroy(sc);
  857         bzero(sc->sc_akey, sizeof(sc->sc_akey));
  858         bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
  859         bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
  860         bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
  861         mtx_unlock(&sc->sc_queue_mtx);
  862         G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
  863 }
  864 
  865 static void
  866 g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
  867 {
  868         struct g_eli_softc *sc;
  869         int *all, *nargs;
  870 
  871         g_topology_assert();
  872 
  873         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  874         if (nargs == NULL) {
  875                 gctl_error(req, "No '%s' argument.", "nargs");
  876                 return;
  877         }
  878         all = gctl_get_paraml(req, "all", sizeof(*all));
  879         if (all == NULL) {
  880                 gctl_error(req, "No '%s' argument.", "all");
  881                 return;
  882         }
  883         if (!*all && *nargs == 0) {
  884                 gctl_error(req, "Too few arguments.");
  885                 return;
  886         }
  887 
  888         if (*all) {
  889                 struct g_geom *gp, *gp2;
  890 
  891                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
  892                         sc = gp->softc;
  893                         if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
  894                                 G_ELI_DEBUG(0,
  895                                     "Device %s is using one-time key, suspend not supported, skipping.",
  896                                     sc->sc_name);
  897                                 continue;
  898                         }
  899                         g_eli_suspend_one(sc, req);
  900                 }
  901         } else {
  902                 const char *prov;
  903                 char param[16];
  904                 int i;
  905 
  906                 for (i = 0; i < *nargs; i++) {
  907                         snprintf(param, sizeof(param), "arg%d", i);
  908                         prov = gctl_get_asciiparam(req, param);
  909                         if (prov == NULL) {
  910                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
  911                                 continue;
  912                         }
  913 
  914                         sc = g_eli_find_device(mp, prov);
  915                         if (sc == NULL) {
  916                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
  917                                 continue;
  918                         }
  919                         g_eli_suspend_one(sc, req);
  920                 }
  921         }
  922 }
  923 
  924 static void
  925 g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
  926 {
  927         struct g_eli_metadata md;
  928         struct g_eli_softc *sc;
  929         struct g_provider *pp;
  930         struct g_consumer *cp;
  931         const char *name;
  932         u_char *key, mkey[G_ELI_DATAIVKEYLEN];
  933         int *nargs, keysize, error;
  934         u_int nkey;
  935 
  936         g_topology_assert();
  937 
  938         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  939         if (nargs == NULL) {
  940                 gctl_error(req, "No '%s' argument.", "nargs");
  941                 return;
  942         }
  943         if (*nargs != 1) {
  944                 gctl_error(req, "Invalid number of arguments.");
  945                 return;
  946         }
  947 
  948         name = gctl_get_asciiparam(req, "arg0");
  949         if (name == NULL) {
  950                 gctl_error(req, "No 'arg%u' argument.", 0);
  951                 return;
  952         }
  953         sc = g_eli_find_device(mp, name);
  954         if (sc == NULL) {
  955                 gctl_error(req, "Provider %s is invalid.", name);
  956                 return;
  957         }
  958         cp = LIST_FIRST(&sc->sc_geom->consumer);
  959         pp = cp->provider;
  960         error = g_eli_read_metadata(mp, pp, &md);
  961         if (error != 0) {
  962                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
  963                     name, error);
  964                 return;
  965         }
  966         if (md.md_keys == 0x00) {
  967                 bzero(&md, sizeof(md));
  968                 gctl_error(req, "No valid keys on %s.", pp->name);
  969                 return;
  970         }
  971 
  972         key = gctl_get_param(req, "key", &keysize);
  973         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
  974                 bzero(&md, sizeof(md));
  975                 gctl_error(req, "No '%s' argument.", "key");
  976                 return;
  977         }
  978 
  979         error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
  980         bzero(key, keysize);
  981         if (error == -1) {
  982                 bzero(&md, sizeof(md));
  983                 gctl_error(req, "Wrong key for %s.", pp->name);
  984                 return;
  985         } else if (error > 0) {
  986                 bzero(&md, sizeof(md));
  987                 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
  988                     pp->name, error);
  989                 return;
  990         }
  991         G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
  992 
  993         mtx_lock(&sc->sc_queue_mtx);
  994         if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
  995                 gctl_error(req, "Device %s is not suspended.", name);
  996         else {
  997                 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
  998                 g_eli_mkey_propagate(sc, mkey);
  999                 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
 1000                 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
 1001                 wakeup(sc);
 1002         }
 1003         mtx_unlock(&sc->sc_queue_mtx);
 1004         bzero(mkey, sizeof(mkey));
 1005         bzero(&md, sizeof(md));
 1006 }
 1007 
 1008 static int
 1009 g_eli_kill_one(struct g_eli_softc *sc)
 1010 {
 1011         struct g_provider *pp;
 1012         struct g_consumer *cp;
 1013         int error = 0;
 1014 
 1015         g_topology_assert();
 1016 
 1017         if (sc == NULL)
 1018                 return (ENOENT);
 1019 
 1020         pp = LIST_FIRST(&sc->sc_geom->provider);
 1021         g_error_provider(pp, ENXIO);
 1022 
 1023         cp = LIST_FIRST(&sc->sc_geom->consumer);
 1024         pp = cp->provider;
 1025 
 1026         if (sc->sc_flags & G_ELI_FLAG_RO) {
 1027                 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
 1028                     "provider: %s.", pp->name);
 1029         } else {
 1030                 u_char *sector;
 1031                 u_int i;
 1032                 int err;
 1033 
 1034                 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
 1035                 for (i = 0; i <= g_eli_overwrites; i++) {
 1036                         if (i == g_eli_overwrites)
 1037                                 bzero(sector, pp->sectorsize);
 1038                         else
 1039                                 arc4rand(sector, pp->sectorsize, 0);
 1040                         err = g_write_data(cp, pp->mediasize - pp->sectorsize,
 1041                             sector, pp->sectorsize);
 1042                         if (err != 0) {
 1043                                 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
 1044                                     "(error=%d).", pp->name, err);
 1045                                 if (error == 0)
 1046                                         error = err;
 1047                         }
 1048                         /*
 1049                          * Flush write cache so we don't overwrite data N times
 1050                          * in cache and only once on disk.
 1051                          */
 1052                         (void)g_io_flush(cp);
 1053                 }
 1054                 free(sector, M_ELI);
 1055         }
 1056         if (error == 0)
 1057                 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
 1058         g_eli_destroy(sc, TRUE);
 1059         return (error);
 1060 }
 1061 
 1062 static void
 1063 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
 1064 {
 1065         int *all, *nargs;
 1066         int error;
 1067 
 1068         g_topology_assert();
 1069 
 1070         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
 1071         if (nargs == NULL) {
 1072                 gctl_error(req, "No '%s' argument.", "nargs");
 1073                 return;
 1074         }
 1075         all = gctl_get_paraml(req, "all", sizeof(*all));
 1076         if (all == NULL) {
 1077                 gctl_error(req, "No '%s' argument.", "all");
 1078                 return;
 1079         }
 1080         if (!*all && *nargs == 0) {
 1081                 gctl_error(req, "Too few arguments.");
 1082                 return;
 1083         }
 1084 
 1085         if (*all) {
 1086                 struct g_geom *gp, *gp2;
 1087 
 1088                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
 1089                         error = g_eli_kill_one(gp->softc);
 1090                         if (error != 0)
 1091                                 gctl_error(req, "Not fully done.");
 1092                 }
 1093         } else {
 1094                 struct g_eli_softc *sc;
 1095                 const char *prov;
 1096                 char param[16];
 1097                 int i;
 1098 
 1099                 for (i = 0; i < *nargs; i++) {
 1100                         snprintf(param, sizeof(param), "arg%d", i);
 1101                         prov = gctl_get_asciiparam(req, param);
 1102                         if (prov == NULL) {
 1103                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
 1104                                 continue;
 1105                         }
 1106 
 1107                         sc = g_eli_find_device(mp, prov);
 1108                         if (sc == NULL) {
 1109                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
 1110                                 continue;
 1111                         }
 1112                         error = g_eli_kill_one(sc);
 1113                         if (error != 0)
 1114                                 gctl_error(req, "Not fully done.");
 1115                 }
 1116         }
 1117 }
 1118 
 1119 void
 1120 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
 1121 {
 1122         uint32_t *version;
 1123 
 1124         g_topology_assert();
 1125 
 1126         version = gctl_get_paraml(req, "version", sizeof(*version));
 1127         if (version == NULL) {
 1128                 gctl_error(req, "No '%s' argument.", "version");
 1129                 return;
 1130         }
 1131         while (*version != G_ELI_VERSION) {
 1132                 if (G_ELI_VERSION == G_ELI_VERSION_06 &&
 1133                     *version == G_ELI_VERSION_05) {
 1134                         /* Compatible. */
 1135                         break;
 1136                 }
 1137                 if (G_ELI_VERSION == G_ELI_VERSION_07 &&
 1138                     (*version == G_ELI_VERSION_05 ||
 1139                      *version == G_ELI_VERSION_06)) {
 1140                         /* Compatible. */
 1141                         break;
 1142                 }
 1143                 gctl_error(req, "Userland and kernel parts are out of sync.");
 1144                 return;
 1145         }
 1146 
 1147         if (strcmp(verb, "attach") == 0)
 1148                 g_eli_ctl_attach(req, mp);
 1149         else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
 1150                 g_eli_ctl_detach(req, mp);
 1151         else if (strcmp(verb, "onetime") == 0)
 1152                 g_eli_ctl_onetime(req, mp);
 1153         else if (strcmp(verb, "configure") == 0)
 1154                 g_eli_ctl_configure(req, mp);
 1155         else if (strcmp(verb, "setkey") == 0)
 1156                 g_eli_ctl_setkey(req, mp);
 1157         else if (strcmp(verb, "delkey") == 0)
 1158                 g_eli_ctl_delkey(req, mp);
 1159         else if (strcmp(verb, "suspend") == 0)
 1160                 g_eli_ctl_suspend(req, mp);
 1161         else if (strcmp(verb, "resume") == 0)
 1162                 g_eli_ctl_resume(req, mp);
 1163         else if (strcmp(verb, "kill") == 0)
 1164                 g_eli_ctl_kill(req, mp);
 1165         else
 1166                 gctl_error(req, "Unknown verb.");
 1167 }

Cache object: 4d84788924058b1e4c73f7f71f9c15db


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.