summaryrefslogtreecommitdiffstats
path: root/sbin/geom/class
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2015-08-08 09:51:38 +0000
committerpjd <pjd@FreeBSD.org>2015-08-08 09:51:38 +0000
commit2ae822a47d155274a8b019dffdb60f0992293ae4 (patch)
tree3d81b92c9c23fdf0dff04d772f0a3ac5e68d5526 /sbin/geom/class
parent349429fe8270f2579de42235749bb5ed010ee83a (diff)
downloadFreeBSD-src-2ae822a47d155274a8b019dffdb60f0992293ae4.zip
FreeBSD-src-2ae822a47d155274a8b019dffdb60f0992293ae4.tar.gz
Enable BIO_DELETE passthru in GELI, so TRIM/UNMAP can work as expected when
GELI is used on a SSD or inside virtual machine, so that guest can tell host that it is no longer using some of the storage. Enabling BIO_DELETE passthru comes with a small security consequence - an attacker can tell how much space is being really used on encrypted device and has less data no analyse then. This is why the -T option can be given to the init subcommand to turn off this behaviour and -t/T options for the configure subcommand can be used to adjust this setting later. PR: 198863 Submitted by: Matthew D. Fuller fullermd at over-yonder dot net This commit also includes a fix from Fabian Keil freebsd-listen at fabiankeil.de for 'configure' on onetime providers which is not strictly related, but is entangled in the same code, so would cause conflicts if separated out.
Diffstat (limited to 'sbin/geom/class')
-rw-r--r--sbin/geom/class/eli/geli.831
-rw-r--r--sbin/geom/class/eli/geom_eli.c66
2 files changed, 82 insertions, 15 deletions
diff --git a/sbin/geom/class/eli/geli.8 b/sbin/geom/class/eli/geli.8
index aac307f..ed425da 100644
--- a/sbin/geom/class/eli/geli.8
+++ b/sbin/geom/class/eli/geli.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 2, 2015
+.Dd July 10, 2015
.Dt GELI 8
.Os
.Sh NAME
@@ -51,7 +51,7 @@ utility:
.Pp
.Nm
.Cm init
-.Op Fl bPv
+.Op Fl bPTv
.Op Fl a Ar aalgo
.Op Fl B Ar backupfile
.Op Fl e Ar ealgo
@@ -80,7 +80,7 @@ utility:
.Cm detach
.Nm
.Cm onetime
-.Op Fl d
+.Op Fl dT
.Op Fl a Ar aalgo
.Op Fl e Ar ealgo
.Op Fl l Ar keylen
@@ -88,7 +88,7 @@ utility:
.Ar prov
.Nm
.Cm configure
-.Op Fl bB
+.Op Fl bBtT
.Ar prov ...
.Nm
.Cm setkey
@@ -351,6 +351,17 @@ Change decrypted provider's sector size.
Increasing the sector size allows increased performance,
because encryption/decryption which requires an initialization vector
is done per sector; fewer sectors means less computational work.
+.It Fl T
+Don't pass through
+.Dv BIO_DELETE
+calls (i.e., TRIM/UNMAP).
+This can prevent an attacker from knowing how much space you're actually
+using and which sectors contain live data, but will also prevent the
+backing store (SSD, etc) from reclaiming space you're not using, which
+may degrade its performance and lifespan.
+The underlying provider may or may not actually obliterate the deleted
+sectors when TRIM is enabled, so it should not be considered to add any
+security.
.It Fl V Ar version
Metadata version to use.
This option is helpful when creating a provider that may be used by older
@@ -456,6 +467,11 @@ Change decrypted provider's sector size.
For more information, see the description of the
.Cm init
subcommand.
+.It Fl T
+Disable TRIM/UNMAP passthru.
+For more information, see the description of the
+.Cm init
+subcommand.
.El
.It Cm configure
Change configuration of the given providers.
@@ -469,6 +485,13 @@ For more information, see the description of the
subcommand.
.It Fl B
Remove the BOOT flag from the given providers.
+.It Fl t
+Enable TRIM/UNMAP passthru.
+For more information, see the description of the
+.Cm init
+subcommand.
+.It Fl T
+Disable TRIM/UNMAP passthru.
.El
.It Cm setkey
Install a copy of the Master Key into the selected slot, encrypted with
diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c
index 502303d..0c6ca2c 100644
--- a/sbin/geom/class/eli/geom_eli.c
+++ b/sbin/geom/class/eli/geom_eli.c
@@ -114,10 +114,11 @@ struct g_command class_commands[] = {
{ 'l', "keylen", "0", G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+ { 'T', "notrim", NULL, G_TYPE_BOOL },
{ 'V', "mdversion", "-1", G_TYPE_NUMBER },
G_OPT_SENTINEL
},
- "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov"
+ "[-bPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov"
},
{ "label", G_FLAG_VERBOSE, eli_main,
{
@@ -170,17 +171,20 @@ struct g_command class_commands[] = {
{ 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING },
{ 'l', "keylen", "0", G_TYPE_NUMBER },
{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+ { 'T', "notrim", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
- "[-d] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov"
+ "[-dT] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov"
},
{ "configure", G_FLAG_VERBOSE, eli_main,
{
{ 'b', "boot", NULL, G_TYPE_BOOL },
{ 'B', "noboot", NULL, G_TYPE_BOOL },
+ { 't', "trim", NULL, G_TYPE_BOOL },
+ { 'T', "notrim", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
- "[-bB] prov ..."
+ "[-bBtT] prov ..."
},
{ "setkey", G_FLAG_VERBOSE, eli_main,
{
@@ -698,6 +702,8 @@ eli_init(struct gctl_req *req)
md.md_flags = 0;
if (gctl_get_int(req, "boot"))
md.md_flags |= G_ELI_FLAG_BOOT;
+ if (gctl_get_int(req, "notrim"))
+ md.md_flags |= G_ELI_FLAG_NODELETE;
md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
str = gctl_get_ascii(req, "aalgo");
if (*str != '\0') {
@@ -899,26 +905,45 @@ eli_attach(struct gctl_req *req)
}
static void
-eli_configure_detached(struct gctl_req *req, const char *prov, bool boot)
+eli_configure_detached(struct gctl_req *req, const char *prov, int boot,
+ int trim)
{
struct g_eli_metadata md;
+ bool changed = 0;
if (eli_metadata_read(req, prov, &md) == -1)
return;
- if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) {
+ if (boot == 1 && (md.md_flags & G_ELI_FLAG_BOOT)) {
if (verbose)
printf("BOOT flag already configured for %s.\n", prov);
- } else if (!boot && !(md.md_flags & G_ELI_FLAG_BOOT)) {
+ } else if (boot == 0 && !(md.md_flags & G_ELI_FLAG_BOOT)) {
if (verbose)
printf("BOOT flag not configured for %s.\n", prov);
- } else {
+ } else if (boot >= 0) {
if (boot)
md.md_flags |= G_ELI_FLAG_BOOT;
else
md.md_flags &= ~G_ELI_FLAG_BOOT;
- eli_metadata_store(req, prov, &md);
+ changed = 1;
+ }
+
+ if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) {
+ if (verbose)
+ printf("TRIM disable flag already configured for %s.\n", prov);
+ } else if (trim == 1 && !(md.md_flags & G_ELI_FLAG_NODELETE)) {
+ if (verbose)
+ printf("TRIM disable flag not configured for %s.\n", prov);
+ } else if (trim >= 0) {
+ if (trim)
+ md.md_flags &= ~G_ELI_FLAG_NODELETE;
+ else
+ md.md_flags |= G_ELI_FLAG_NODELETE;
+ changed = 1;
}
+
+ if (changed)
+ eli_metadata_store(req, prov, &md);
bzero(&md, sizeof(md));
}
@@ -926,7 +951,8 @@ static void
eli_configure(struct gctl_req *req)
{
const char *prov;
- bool boot, noboot;
+ bool boot, noboot, trim, notrim;
+ int doboot, dotrim;
int i, nargs;
nargs = gctl_get_int(req, "nargs");
@@ -937,12 +963,30 @@ eli_configure(struct gctl_req *req)
boot = gctl_get_int(req, "boot");
noboot = gctl_get_int(req, "noboot");
+ trim = gctl_get_int(req, "trim");
+ notrim = gctl_get_int(req, "notrim");
+ doboot = -1;
if (boot && noboot) {
gctl_error(req, "Options -b and -B are mutually exclusive.");
return;
}
- if (!boot && !noboot) {
+ if (boot)
+ doboot = 1;
+ else if (noboot)
+ doboot = 0;
+
+ dotrim = -1;
+ if (trim && notrim) {
+ gctl_error(req, "Options -t and -T are mutually exclusive.");
+ return;
+ }
+ if (trim)
+ dotrim = 1;
+ else if (notrim)
+ dotrim = 0;
+
+ if (doboot == -1 && dotrim == -1) {
gctl_error(req, "No option given.");
return;
}
@@ -953,7 +997,7 @@ eli_configure(struct gctl_req *req)
for (i = 0; i < nargs; i++) {
prov = gctl_get_ascii(req, "arg%d", i);
if (!eli_is_attached(prov))
- eli_configure_detached(req, prov, boot);
+ eli_configure_detached(req, prov, doboot, dotrim);
}
}
OpenPOWER on IntegriCloud