File openssh-6.6p1-prevent_private_key_leakage.patch of Package openssh.10219
# HG changeset patch
# Parent 8c44bbed35a9beacbc1f647e5b4bb9f2501a4805
Pre-allocare buffer for private keys data to prevent leaking of sensitive data
via heap.
CVE-2016-10011
bsc#1016369
backported upstream commit 54d022026aae4f53fa74cc636e4a032d9689b64d
backported upstream commit a9c746088787549bb5b1ae3add7d06a1b6d93d5e
diff --git a/openssh-6.6p1/authfile.c b/openssh-6.6p1/authfile.c
--- a/openssh-6.6p1/authfile.c
+++ b/openssh-6.6p1/authfile.c
@@ -689,34 +689,44 @@ key_load_file(int fd, const char *filena
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
st.st_size > MAX_KEY_FILE_SIZE) {
toobig:
error("%s: key file %.200s%stoo large", __func__,
filename == NULL ? "" : filename,
filename == NULL ? "" : " ");
return 0;
}
+ /*
+ * Pre-allocate the buffer used for the key contents and clamp its
+ * maximum size. This ensures that key contents are never leaked via
+ * implicit realloc() in the sshbuf code.
+ */
+ if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) {
+ st.st_size = 64*1024; /* 64k should be enough for anyone :) */
+ }
+ buffer_append_space(blob, st.st_size);
buffer_clear(blob);
for (;;) {
if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
if (errno == EPIPE)
break;
debug("%s: read from key file %.200s%sfailed: %.100s",
__func__, filename == NULL ? "" : filename,
filename == NULL ? "" : " ", strerror(errno));
buffer_clear(blob);
explicit_bzero(buf, sizeof(buf));
return 0;
}
- buffer_append(blob, buf, len);
- if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
+ /* first check limits to prevent automatic buffer blow-up */
+ if (buffer_len(blob) + len > (u_int)st.st_size) {
buffer_clear(blob);
explicit_bzero(buf, sizeof(buf));
goto toobig;
}
+ buffer_append(blob, buf, len);
}
explicit_bzero(buf, sizeof(buf));
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
st.st_size != buffer_len(blob)) {
debug("%s: key file %.200s%schanged size while reading",
__func__, filename == NULL ? "" : filename,
filename == NULL ? "" : " ");
buffer_clear(blob);