Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Aug 2018 00:47:25 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r337216 - vendor-sys/illumos/dist/common/nvpair
Message-ID:  <201808030047.w730lPL3055635@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Aug  3 00:47:24 2018
New Revision: 337216
URL: https://svnweb.freebsd.org/changeset/base/337216

Log:
  7263 deeply nested nvlist can overflow stack
  
  illumos/illumos-gate@9ca527c3d3dfa7c8f304b34a9e03b5eddace838f
  
  Reviewed by: Adam Leventhal <ahl@delphix.com>
  Reviewed by: George Wilson <george.wilson@delphix.com>
  Reviewed by: Robert Mustacchi <rm@joyent.com>
  Approved by: Dan McDonald <danmcd@omniti.com>
  Author: Matthew Ahrens <mahrens@delphix.com>

Modified:
  vendor-sys/illumos/dist/common/nvpair/nvpair.c

Modified: vendor-sys/illumos/dist/common/nvpair/nvpair.c
==============================================================================
--- vendor-sys/illumos/dist/common/nvpair/nvpair.c	Fri Aug  3 00:24:27 2018	(r337215)
+++ vendor-sys/illumos/dist/common/nvpair/nvpair.c	Fri Aug  3 00:47:24 2018	(r337216)
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  */
 
 #include <sys/stropts.h>
@@ -138,6 +139,11 @@ static int nvlist_add_common(nvlist_t *nvl, const char
 #define	NVPAIR2I_NVP(nvp) \
 	((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
 
+#ifdef _KERNEL
+int nvpair_max_recursion = 20;
+#else
+int nvpair_max_recursion = 100;
+#endif
 
 int
 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
@@ -2014,6 +2020,7 @@ typedef struct {
 	const nvs_ops_t	*nvs_ops;
 	void		*nvs_private;
 	nvpriv_t	*nvs_priv;
+	int		nvs_recursion;
 } nvstream_t;
 
 /*
@@ -2165,9 +2172,16 @@ static int
 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
 {
 	switch (nvs->nvs_op) {
-	case NVS_OP_ENCODE:
-		return (nvs_operation(nvs, embedded, NULL));
+	case NVS_OP_ENCODE: {
+		int err;
 
+		if (nvs->nvs_recursion >= nvpair_max_recursion)
+			return (EINVAL);
+		nvs->nvs_recursion++;
+		err = nvs_operation(nvs, embedded, NULL);
+		nvs->nvs_recursion--;
+		return (err);
+	}
 	case NVS_OP_DECODE: {
 		nvpriv_t *priv;
 		int err;
@@ -2180,8 +2194,12 @@ nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
 
 		nvlist_init(embedded, embedded->nvl_nvflag, priv);
 
+		if (nvs->nvs_recursion >= nvpair_max_recursion)
+			return (EINVAL);
+		nvs->nvs_recursion++;
 		if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
 			nvlist_free(embedded);
+		nvs->nvs_recursion--;
 		return (err);
 	}
 	default:
@@ -2269,6 +2287,7 @@ nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen
 		return (EINVAL);
 
 	nvs.nvs_op = nvs_op;
+	nvs.nvs_recursion = 0;
 
 	/*
 	 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and



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