[PATCH] nis: Fix stack overflow (stack exhaustion) in yp_all (bug 34528)

Florian Weimer <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
The fix relies on the XDRMAXRECORD limit imposed in yp_xdr.c.
The bug was present from the beginning.

---
 nis/ypclnt.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 455d80df1f..83bafb5151 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -685,23 +685,36 @@ __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
 	{
 	case YP_TRUE:
 	  {
-	    char key[resp.ypresp_all_u.val.key.keydat_len + 1];
-	    char val[resp.ypresp_all_u.val.val.valdat_len + 1];
-	    int keylen = resp.ypresp_all_u.val.key.keydat_len;
-	    int vallen = resp.ypresp_all_u.val.val.valdat_len;
 
 	    /* We are not allowed to modify the key and val data.
 	       But we are allowed to add data behind the buffer,
 	       if we don't modify the length. So add an extra NUL
 	       character to avoid trouble with broken code. */
+
+	    size_t keylen = resp.ypresp_all_u.val.key.keydat_len;
+	    size_t vallen = resp.ypresp_all_u.val.val.valdat_len;
+	    /* Cannot overflow due to the XDRMAXRECORD limit in yp_xdr.c.  */
+	    size_t keyval_size = keylen + vallen + 2;
+	    char *buffer = malloc (keyval_size);
+	    if (buffer == NULL)
+	      {
+		xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+		objp->status = YP_YPERR;
+		return FALSE;
+	      }
+
 	    objp->status = YP_TRUE;
-	    *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
-				  keylen)) = '\0';
-	    *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
-				  vallen)) = '\0';
+	    buffer[keylen] = '\0';
+	    buffer[keyval_size - 1] = '\0';
+	    char *val = buffer + keylen + 1;
+	    memcpy (buffer, resp.ypresp_all_u.val.key.keydat_val, keylen);
+	    memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
 	    xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
-	    if ((*objp->foreach) (objp->status, key, keylen,
-				  val, vallen, objp->data))
+
+	    bool ok = (*objp->foreach) (objp->status, buffer, keylen,
+					val, vallen, objp->data);
+	    free (buffer);
+	    if (ok)
 	      return TRUE;
 	  }
 	  break;

base-commit: 6144ef08960e1db191db2054abef02d361042018
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.