Allow geli to operate on read-only providers.
Initial patch from: vd MFC after: 2 weeks
This commit is contained in:
parent
edd5ce3102
commit
850590166f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=161127
@ -64,7 +64,7 @@ utility:
|
||||
.Cm init
|
||||
.Nm
|
||||
.Cm attach
|
||||
.Op Fl dpv
|
||||
.Op Fl dprv
|
||||
.Op Fl k Ar keyfile
|
||||
.Ar prov
|
||||
.Nm
|
||||
@ -288,6 +288,8 @@ Probably a better choice is the
|
||||
option for the
|
||||
.Cm detach
|
||||
subcommand.
|
||||
.It Fl r
|
||||
Attach read-only provider. It will not be opened for writting.
|
||||
.It Fl k Ar keyfile
|
||||
Specifies a file which contains part of the key.
|
||||
For more information see the description of the
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -78,7 +78,7 @@ static void eli_dump(struct gctl_req *req);
|
||||
*
|
||||
* init [-bhPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov
|
||||
* label - alias for 'init'
|
||||
* attach [-dpv] [-k keyfile] prov
|
||||
* attach [-dprv] [-k keyfile] prov
|
||||
* detach [-fl] prov ...
|
||||
* stop - alias for 'detach'
|
||||
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov ...
|
||||
@ -124,9 +124,10 @@ struct g_command class_commands[] = {
|
||||
{ 'd', "detach", NULL, G_TYPE_NONE },
|
||||
{ 'k', "keyfile", keyfile, G_TYPE_STRING },
|
||||
{ 'p', "nopassphrase", NULL, G_TYPE_NONE },
|
||||
{ 'r', "readonly", NULL, G_TYPE_NONE },
|
||||
G_OPT_SENTINEL
|
||||
},
|
||||
"[-dpv] [-k keyfile] prov"
|
||||
"[-dprv] [-k keyfile] prov"
|
||||
},
|
||||
{ "detach", 0, NULL,
|
||||
{
|
||||
|
@ -455,6 +455,10 @@ g_eli_access(struct g_provider *pp, int dr, int dw, int de)
|
||||
sc = gp->softc;
|
||||
|
||||
if (dw > 0) {
|
||||
if (sc->sc_flags & G_ELI_FLAG_RO) {
|
||||
/* Deny write attempts. */
|
||||
return (EROFS);
|
||||
}
|
||||
/* Someone is opening us for write, we need to remember that. */
|
||||
sc->sc_flags |= G_ELI_FLAG_WOPEN;
|
||||
return (0);
|
||||
@ -495,19 +499,19 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
|
||||
gp->start = g_eli_start;
|
||||
/*
|
||||
* Spoiling cannot happen actually, because we keep provider open for
|
||||
* writing all the time.
|
||||
* writing all the time or provider is read-only.
|
||||
*/
|
||||
gp->spoiled = g_eli_orphan_spoil_assert;
|
||||
gp->orphan = g_eli_orphan;
|
||||
gp->dumpconf = g_eli_dumpconf;
|
||||
/*
|
||||
* If detach-on-last-close feature is not enabled, we can simply use
|
||||
* g_std_access().
|
||||
* If detach-on-last-close feature is not enabled and we don't operate
|
||||
* on read-only provider, we can simply use g_std_access().
|
||||
*/
|
||||
if (md->md_flags & G_ELI_FLAG_WO_DETACH)
|
||||
if (md->md_flags & (G_ELI_FLAG_WO_DETACH | G_ELI_FLAG_RO))
|
||||
gp->access = g_eli_access;
|
||||
else
|
||||
gp->access = g_std_access;
|
||||
gp->dumpconf = g_eli_dumpconf;
|
||||
|
||||
sc->sc_crypto = G_ELI_CRYPTO_SW;
|
||||
sc->sc_flags = md->md_flags;
|
||||
@ -578,8 +582,13 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
|
||||
* Keep provider open all the time, so we can run critical tasks,
|
||||
* like Master Keys deletion, without wondering if we can open
|
||||
* provider or not.
|
||||
* We don't open provider for writing only when user requested read-only
|
||||
* access.
|
||||
*/
|
||||
error = g_access(cp, 1, 1, 1);
|
||||
if (sc->sc_flags & G_ELI_FLAG_RO)
|
||||
error = g_access(cp, 1, 0, 1);
|
||||
else
|
||||
error = g_access(cp, 1, 1, 1);
|
||||
if (error != 0) {
|
||||
if (req != NULL) {
|
||||
gctl_error(req, "Cannot access %s (error=%d).",
|
||||
@ -997,6 +1006,7 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
ADD_FLAG(G_ELI_FLAG_AUTH, "AUTH");
|
||||
ADD_FLAG(G_ELI_FLAG_WOPEN, "W-OPEN");
|
||||
ADD_FLAG(G_ELI_FLAG_DESTROY, "DESTROY");
|
||||
ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY");
|
||||
#undef ADD_FLAG
|
||||
}
|
||||
sbuf_printf(sb, "</Flags>\n");
|
||||
|
@ -59,6 +59,7 @@
|
||||
*/
|
||||
#define G_ELI_VERSION 1
|
||||
|
||||
/* ON DISK FLAGS. */
|
||||
/* Use random, onetime keys. */
|
||||
#define G_ELI_FLAG_ONETIME 0x00000001
|
||||
/* Ask for the passphrase from the kernel, before mounting root. */
|
||||
@ -69,6 +70,9 @@
|
||||
#define G_ELI_FLAG_RW_DETACH 0x00000008
|
||||
/* Provide data authentication. */
|
||||
#define G_ELI_FLAG_AUTH 0x00000010
|
||||
/* Provider is read-only, we should deny all write attempts. */
|
||||
#define G_ELI_FLAG_RO 0x00000020
|
||||
/* RUNTIME FLAGS. */
|
||||
/* Provider was open for writing. */
|
||||
#define G_ELI_FLAG_WOPEN 0x00010000
|
||||
/* Destroy device. */
|
||||
|
@ -57,7 +57,7 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
|
||||
struct g_provider *pp;
|
||||
const char *name;
|
||||
u_char *key, mkey[G_ELI_DATAIVKEYLEN];
|
||||
int *nargs, *detach;
|
||||
int *nargs, *detach, *readonly;
|
||||
int keysize, error;
|
||||
u_int nkey;
|
||||
|
||||
@ -79,6 +79,12 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
|
||||
return;
|
||||
}
|
||||
|
||||
readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
|
||||
if (readonly == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "readonly");
|
||||
return;
|
||||
}
|
||||
|
||||
name = gctl_get_asciiparam(req, "arg0");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||
@ -124,8 +130,16 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
|
||||
}
|
||||
G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
|
||||
|
||||
if (*detach && *readonly) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "Options -d and -r are mutually exclusive.",
|
||||
pp->name, error);
|
||||
return;
|
||||
}
|
||||
if (*detach)
|
||||
md.md_flags |= G_ELI_FLAG_WO_DETACH;
|
||||
if (*readonly)
|
||||
md.md_flags |= G_ELI_FLAG_RO;
|
||||
g_eli_create(req, mp, pp, &md, mkey, nkey);
|
||||
bzero(mkey, sizeof(mkey));
|
||||
bzero(&md, sizeof(md));
|
||||
@ -374,6 +388,10 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
if (sc->sc_flags & G_ELI_FLAG_RO) {
|
||||
gctl_error(req, "Cannot change keys for read-only provider.");
|
||||
return;
|
||||
}
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
@ -483,6 +501,10 @@ g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
if (sc->sc_flags & G_ELI_FLAG_RO) {
|
||||
gctl_error(req, "Cannot delete keys for read-only provider.");
|
||||
return;
|
||||
}
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
@ -565,9 +587,7 @@ g_eli_kill_one(struct g_eli_softc *sc)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
struct g_consumer *cp;
|
||||
u_char *sector;
|
||||
int err, error = 0;
|
||||
u_int i;
|
||||
int error = 0;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
@ -580,22 +600,31 @@ g_eli_kill_one(struct g_eli_softc *sc)
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
|
||||
for (i = 0; i <= g_eli_overwrites; i++) {
|
||||
if (i == g_eli_overwrites)
|
||||
bzero(sector, pp->sectorsize);
|
||||
else
|
||||
arc4rand(sector, pp->sectorsize, 0);
|
||||
err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
|
||||
pp->sectorsize);
|
||||
if (err != 0) {
|
||||
G_ELI_DEBUG(0, "Cannot erase metadata on %s "
|
||||
"(error=%d).", pp->name, err);
|
||||
if (error == 0)
|
||||
error = err;
|
||||
if (sc->sc_flags & G_ELI_FLAG_RO) {
|
||||
G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
|
||||
"provider: %s.", pp->name);
|
||||
} else {
|
||||
u_char *sector;
|
||||
u_int i;
|
||||
int err;
|
||||
|
||||
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
|
||||
for (i = 0; i <= g_eli_overwrites; i++) {
|
||||
if (i == g_eli_overwrites)
|
||||
bzero(sector, pp->sectorsize);
|
||||
else
|
||||
arc4rand(sector, pp->sectorsize, 0);
|
||||
err = g_write_data(cp, pp->mediasize - pp->sectorsize,
|
||||
sector, pp->sectorsize);
|
||||
if (err != 0) {
|
||||
G_ELI_DEBUG(0, "Cannot erase metadata on %s "
|
||||
"(error=%d).", pp->name, err);
|
||||
if (error == 0)
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
free(sector, M_ELI);
|
||||
}
|
||||
free(sector, M_ELI);
|
||||
if (error == 0)
|
||||
G_ELI_DEBUG(0, "%s has been killed.", pp->name);
|
||||
g_eli_destroy(sc, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user