Author: mav
Date: Fri Aug  3 01:09:12 2018
New Revision: 337217
URL: https://svnweb.freebsd.org/changeset/base/337217

Log:
  MFV r337216: 7263 deeply nested nvlist can overflow stack
  
  illumos/illumos-gate@9ca527c3d3dfa7c8f304b34a9e03b5eddace838f
  
  Reviewed by: Adam Leventhal <a...@delphix.com>
  Reviewed by: George Wilson <george.wil...@delphix.com>
  Reviewed by: Robert Mustacchi <r...@joyent.com>
  Approved by: Dan McDonald <dan...@omniti.com>
  Author: Matthew Ahrens <mahr...@delphix.com>

Modified:
  head/sys/cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c        
Fri Aug  3 00:47:24 2018        (r337216)
+++ head/sys/cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c        
Fri Aug  3 01:09:12 2018        (r337217)
@@ -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/debug.h>
@@ -142,6 +143,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 */ ...)
@@ -2018,6 +2024,7 @@ typedef struct {
        const nvs_ops_t *nvs_ops;
        void            *nvs_private;
        nvpriv_t        *nvs_priv;
+       int             nvs_recursion;
 } nvstream_t;
 
 /*
@@ -2169,9 +2176,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;
@@ -2184,8 +2198,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:
@@ -2273,6 +2291,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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to