Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4c5efdb authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Theodore Ts'o
Browse files

random: add and use memzero_explicit() for clearing data



zatimend has reported that in his environment (3.16/gcc4.8.3/corei7)
memset() calls which clear out sensitive data in extract_{buf,entropy,
entropy_user}() in random driver are being optimized away by gcc.

Add a helper memzero_explicit() (similarly as explicit_bzero() variants)
that can be used in such cases where a variable with sensitive data is
being cleared out in the end. Other use cases might also be in crypto
code. [ I have put this into lib/string.c though, as it's always built-in
and doesn't need any dependencies then. ]

Fixes kernel bugzilla: 82041

Reported-by: default avatar <zatimend@hotmail.co.uk>
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
parent 7d1311b9
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -1106,7 +1106,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
	__mix_pool_bytes(r, hash.w, sizeof(hash.w));
	__mix_pool_bytes(r, hash.w, sizeof(hash.w));
	spin_unlock_irqrestore(&r->lock, flags);
	spin_unlock_irqrestore(&r->lock, flags);


	memset(workspace, 0, sizeof(workspace));
	memzero_explicit(workspace, sizeof(workspace));


	/*
	/*
	 * In case the hash function has some recognizable output
	 * In case the hash function has some recognizable output
@@ -1118,7 +1118,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
	hash.w[2] ^= rol32(hash.w[2], 16);
	hash.w[2] ^= rol32(hash.w[2], 16);


	memcpy(out, &hash, EXTRACT_SIZE);
	memcpy(out, &hash, EXTRACT_SIZE);
	memset(&hash, 0, sizeof(hash));
	memzero_explicit(&hash, sizeof(hash));
}
}


/*
/*
@@ -1175,7 +1175,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
	}
	}


	/* Wipe data just returned from memory */
	/* Wipe data just returned from memory */
	memset(tmp, 0, sizeof(tmp));
	memzero_explicit(tmp, sizeof(tmp));


	return ret;
	return ret;
}
}
@@ -1218,7 +1218,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
	}
	}


	/* Wipe data just returned from memory */
	/* Wipe data just returned from memory */
	memset(tmp, 0, sizeof(tmp));
	memzero_explicit(tmp, sizeof(tmp));


	return ret;
	return ret;
}
}
+3 −2
Original line number Original line Diff line number Diff line
@@ -144,7 +144,8 @@ static inline bool strstarts(const char *str, const char *prefix)
	return strncmp(str, prefix, strlen(prefix)) == 0;
	return strncmp(str, prefix, strlen(prefix)) == 0;
}
}


extern size_t memweight(const void *ptr, size_t bytes);
size_t memweight(const void *ptr, size_t bytes);
void memzero_explicit(void *s, size_t count);


/**
/**
 * kbasename - return the last part of a pathname.
 * kbasename - return the last part of a pathname.
+16 −0
Original line number Original line Diff line number Diff line
@@ -604,6 +604,22 @@ void *memset(void *s, int c, size_t count)
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memset);
#endif
#endif


/**
 * memzero_explicit - Fill a region of memory (e.g. sensitive
 *		      keying data) with 0s.
 * @s: Pointer to the start of the area.
 * @count: The size of the area.
 *
 * memzero_explicit() doesn't need an arch-specific version as
 * it just invokes the one of memset() implicitly.
 */
void memzero_explicit(void *s, size_t count)
{
	memset(s, 0, count);
	OPTIMIZER_HIDE_VAR(s);
}
EXPORT_SYMBOL(memzero_explicit);

#ifndef __HAVE_ARCH_MEMCPY
#ifndef __HAVE_ARCH_MEMCPY
/**
/**
 * memcpy - Copy one area of memory to another
 * memcpy - Copy one area of memory to another