Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Mar 2018 02:15:46 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330726 - in stable/11: sbin/geom/class/cache sbin/geom/class/concat sbin/geom/class/journal sbin/geom/class/label sbin/geom/class/mirror sbin/geom/class/raid3 sbin/geom/class/shsec sbi...
Message-ID:  <201803100215.w2A2FkqY074051@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Sat Mar 10 02:15:45 2018
New Revision: 330726
URL: https://svnweb.freebsd.org/changeset/base/330726

Log:
  MFC r323314, r323338, r328849
  
  r323314:
  Audit userspace geom code for leaking memory to disk
  
  Any geom class using g_metadata_store, as well as geom_virstor which
  duplicated g_metadata_store internally, would dump sectorsize - mdsize bytes
  of userspace memory following the metadata block stored. This is most or all
  geom classes (gcache, gconcat, geli, gjournal, glabel, gmirror, gmultipath,
  graid3, gshsec, gstripe, and geom_virstor).
  
  PR:		222077 (comment #3)
  Reported by:	Maxim Khitrov <max AT mxcrypt.com>
  Reviewed by:	des
  Security:	yes
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D12269
  
  r323338:
  Fix information leak in geli(8) integrity mode
  
  In integrity mode, a larger logical sector (e.g., 4096 bytes) spans several
  physical sectors (e.g., 512 bytes) on the backing device.  Due to hash
  overhead, a 4096 byte logical sector takes 8.5625 512-byte physical sectors.
  This means that only 288 bytes (256 data + 32 hash) of the last 512 byte
  sector are used.
  
  The memory allocation used to store the encrypted data to be written to the
  physical sectors comes from malloc(9) and does not use M_ZERO.
  
  Previously, nothing initialized the final physical sector backing each
  logical sector, aside from the hash + encrypted data portion.  So 224 bytes
  of kernel heap memory was leaked to every block :-(.
  
  This patch addresses the issue by initializing the trailing portion of the
  physical sector in every logical sector to zeros before use.  A much simpler
  but higher overhead fix would be to tag the entire allocation M_ZERO.
  
  PR:		222077
  Reported by:	Maxim Khitrov <max AT mxcrypt.com>
  Reviewed by:	emaste
  Security:	yes
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D12272
  
  r328849:
  geom: don't write stack garbage in disk labels
  
  Most consumers of g_metadata_store were passing in partially unallocated
  memory, resulting in stack garbage being written to disk labels. Fix them by
  zeroing the memory first.
  
  gvirstor repeated the same mistake, but in the kernel.
  
  Also, glabel's label contained a fixed-size string that wasn't
  initialized to zero.
  
  PR:		222077
  Reported by:	Maxim Khitrov <max@mxcrypt.com>
  Reviewed by:	cem
  X-MFC-With:	323314
  X-MFC-With:	323338
  Differential Revision:	https://reviews.freebsd.org/D14164

Modified:
  stable/11/sbin/geom/class/cache/geom_cache.c
  stable/11/sbin/geom/class/concat/geom_concat.c
  stable/11/sbin/geom/class/journal/geom_journal.c
  stable/11/sbin/geom/class/label/geom_label.c
  stable/11/sbin/geom/class/mirror/geom_mirror.c
  stable/11/sbin/geom/class/raid3/geom_raid3.c
  stable/11/sbin/geom/class/shsec/geom_shsec.c
  stable/11/sbin/geom/class/stripe/geom_stripe.c
  stable/11/sbin/geom/class/virstor/geom_virstor.c
  stable/11/sbin/geom/misc/subr.c
  stable/11/sys/geom/eli/g_eli_integrity.c
  stable/11/sys/geom/virstor/g_virstor.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/geom/class/cache/geom_cache.c
==============================================================================
--- stable/11/sbin/geom/class/cache/geom_cache.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/cache/geom_cache.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -137,6 +137,7 @@ cache_label(struct gctl_req *req)
 	int error, nargs;
 	intmax_t val;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs != 2) {
 		gctl_error(req, "Invalid number of arguments.");

Modified: stable/11/sbin/geom/class/concat/geom_concat.c
==============================================================================
--- stable/11/sbin/geom/class/concat/geom_concat.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/concat/geom_concat.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -119,6 +119,7 @@ concat_label(struct gctl_req *req)
 	const char *name;
 	int error, i, hardcode, nargs;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs < 2) {
 		gctl_error(req, "Too few arguments.");

Modified: stable/11/sbin/geom/class/journal/geom_journal.c
==============================================================================
--- stable/11/sbin/geom/class/journal/geom_journal.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/journal/geom_journal.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -144,6 +144,7 @@ journal_label(struct gctl_req *req)
 	intmax_t jsize, msize, ssize;
 	int error, force, i, nargs, checksum, hardcode;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	str = NULL;	/* gcc */
 

Modified: stable/11/sbin/geom/class/label/geom_label.c
==============================================================================
--- stable/11/sbin/geom/class/label/geom_label.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/label/geom_label.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -125,6 +125,7 @@ label_label(struct gctl_req *req)
 	u_char sector[512];
 	int error, nargs;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs != 2) {
 		gctl_error(req, "Invalid number of arguments.");
@@ -145,6 +146,7 @@ label_label(struct gctl_req *req)
 	strlcpy(md.md_magic, G_LABEL_MAGIC, sizeof(md.md_magic));
 	md.md_version = G_LABEL_VERSION;
 	label = gctl_get_ascii(req, "arg0");
+	bzero(md.md_label, sizeof(md.md_label));
 	strlcpy(md.md_label, label, sizeof(md.md_label));
 	md.md_provsize = g_get_mediasize(name);
 	if (md.md_provsize == 0) {

Modified: stable/11/sbin/geom/class/mirror/geom_mirror.c
==============================================================================
--- stable/11/sbin/geom/class/mirror/geom_mirror.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/mirror/geom_mirror.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -188,6 +188,7 @@ mirror_label(struct gctl_req *req)
 	intmax_t val;
 	int error, i, nargs, bal, hardcode;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs < 2) {
 		gctl_error(req, "Too few arguments.");

Modified: stable/11/sbin/geom/class/raid3/geom_raid3.c
==============================================================================
--- stable/11/sbin/geom/class/raid3/geom_raid3.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/raid3/geom_raid3.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -151,6 +151,7 @@ raid3_label(struct gctl_req *req)
 	int hardcode, round_robin, verify;
 	int error, i, nargs;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs < 4) {
 		gctl_error(req, "Too few arguments.");

Modified: stable/11/sbin/geom/class/shsec/geom_shsec.c
==============================================================================
--- stable/11/sbin/geom/class/shsec/geom_shsec.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/shsec/geom_shsec.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -112,6 +112,7 @@ shsec_label(struct gctl_req *req)
 	const char *name;
 	int error, i, nargs, hardcode;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs <= 2) {
 		gctl_error(req, "Too few arguments.");

Modified: stable/11/sbin/geom/class/stripe/geom_stripe.c
==============================================================================
--- stable/11/sbin/geom/class/stripe/geom_stripe.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/stripe/geom_stripe.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -130,6 +130,7 @@ stripe_label(struct gctl_req *req)
 	const char *name;
 	int error, i, nargs, hardcode;
 
+	bzero(sector, sizeof(sector));
 	nargs = gctl_get_int(req, "nargs");
 	if (nargs < 3) {
 		gctl_error(req, "Too few arguments.");

Modified: stable/11/sbin/geom/class/virstor/geom_virstor.c
==============================================================================
--- stable/11/sbin/geom/class/virstor/geom_virstor.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/class/virstor/geom_virstor.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -185,6 +185,7 @@ my_g_metadata_store(const char *name, u_char *md, size
 		goto out;
 	}
 	bcopy(md, sector, size);
+	bzero(sector + size, sectorsize - size);
 	if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) !=
 	    (ssize_t)sectorsize) {
 		error = errno;

Modified: stable/11/sbin/geom/misc/subr.c
==============================================================================
--- stable/11/sbin/geom/misc/subr.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sbin/geom/misc/subr.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -273,6 +273,13 @@ out:
 	return (error);
 }
 
+/* 
+ * Actually write the GEOM label to the provider
+ *
+ * @param name	GEOM provider's name (ie "ada0")
+ * @param md	Pointer to the label data to write
+ * @param size	Size of the data pointed to by md
+ */
 int
 g_metadata_store(const char *name, const unsigned char *md, size_t size)
 {
@@ -304,6 +311,7 @@ g_metadata_store(const char *name, const unsigned char
 		goto out;
 	}
 	bcopy(md, sector, size);
+	bzero(sector + size, sectorsize - size);
 	if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) !=
 	    sectorsize) {
 		error = errno;

Modified: stable/11/sys/geom/eli/g_eli_integrity.c
==============================================================================
--- stable/11/sys/geom/eli/g_eli_integrity.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sys/geom/eli/g_eli_integrity.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -458,8 +458,16 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp
 		authkey = (u_char *)p;		p += G_ELI_AUTH_SECKEYLEN;
 
 		data_secsize = sc->sc_data_per_sector;
-		if ((i % lsec) == 0)
+		if ((i % lsec) == 0) {
 			data_secsize = decr_secsize % data_secsize;
+			/*
+			 * Last encrypted sector of each decrypted sector is
+			 * only partially filled.
+			 */
+			if (bp->bio_cmd == BIO_WRITE)
+				memset(data + sc->sc_alen + data_secsize, 0,
+				    encr_secsize - sc->sc_alen - data_secsize);
+		}
 
 		if (bp->bio_cmd == BIO_READ) {
 			/* Remember read HMAC. */

Modified: stable/11/sys/geom/virstor/g_virstor.c
==============================================================================
--- stable/11/sys/geom/virstor/g_virstor.c	Sat Mar 10 02:13:48 2018	(r330725)
+++ stable/11/sys/geom/virstor/g_virstor.c	Sat Mar 10 02:15:45 2018	(r330726)
@@ -1040,6 +1040,7 @@ write_metadata(struct g_consumer *cp, struct g_virstor
 	pp = cp->provider;
 
 	buf = malloc(pp->sectorsize, M_GVIRSTOR, M_WAITOK);
+	bzero(buf, pp->sectorsize);
 	virstor_metadata_encode(md, buf);
 	g_topology_unlock();
 	error = g_write_data(cp, pp->mediasize - pp->sectorsize, buf,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803100215.w2A2FkqY074051>