summaryrefslogtreecommitdiff
path: root/sshbuf.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-11-16 06:10:29 +0000
committerDamien Miller <djm@mindrot.org>2018-11-16 17:18:29 +1100
commit15182fd96845a03216d7ac5a2cf31c4e77e406e3 (patch)
tree5ddf18f5eefed91be37b61c95381e3fb28476aff /sshbuf.c
parent2a35862e664afde774d4a72497d394fe7306ccb5 (diff)
upstream: make grandparent-parent-child sshbuf chains robust to
use-after-free faults if the ancestors are freed before the descendents. Nothing in OpenSSH uses this deallocation pattern. Reported by Jann Horn OpenBSD-Commit-ID: d93501d1d2734245aac802a252b9bb2eccdba0f2
Diffstat (limited to 'sshbuf.c')
-rw-r--r--sshbuf.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/sshbuf.c b/sshbuf.c
index 20ddf9eb6..adfddf775 100644
--- a/sshbuf.c
+++ b/sshbuf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshbuf.c,v 1.12 2018/07/09 21:56:06 markus Exp $ */ 1/* $OpenBSD: sshbuf.c,v 1.13 2018/11/16 06:10:29 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -143,12 +143,7 @@ sshbuf_free(struct sshbuf *buf)
143 */ 143 */
144 if (sshbuf_check_sanity(buf) != 0) 144 if (sshbuf_check_sanity(buf) != 0)
145 return; 145 return;
146 /* 146
147 * If we are a child, the free our parent to decrement its reference
148 * count and possibly free it.
149 */
150 sshbuf_free(buf->parent);
151 buf->parent = NULL;
152 /* 147 /*
153 * If we are a parent with still-extant children, then don't free just 148 * If we are a parent with still-extant children, then don't free just
154 * yet. The last child's call to sshbuf_free should decrement our 149 * yet. The last child's call to sshbuf_free should decrement our
@@ -157,6 +152,14 @@ sshbuf_free(struct sshbuf *buf)
157 buf->refcount--; 152 buf->refcount--;
158 if (buf->refcount > 0) 153 if (buf->refcount > 0)
159 return; 154 return;
155
156 /*
157 * If we are a child, the free our parent to decrement its reference
158 * count and possibly free it.
159 */
160 sshbuf_free(buf->parent);
161 buf->parent = NULL;
162
160 if (!buf->readonly) { 163 if (!buf->readonly) {
161 explicit_bzero(buf->d, buf->alloc); 164 explicit_bzero(buf->d, buf->alloc);
162 free(buf->d); 165 free(buf->d);