[meta-networking] net-snmp: Fix CVE-2019-20892

Submitted by Wenlin Kang on July 13, 2020, 10:05 a.m. | Patch ID: 174415

Details

Message ID 20200713100529.87717-1-wenlin.kang@windriver.com
State Under Review
Delegated to: Armin Kuster
Headers show

Commit Message

Wenlin Kang July 13, 2020, 10:05 a.m.
Fix CVE-2019-20892

Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
---
 ...oduce-a-reference-count-in-struct-us.patch | 166 ++++++++++++++++++
 .../net-snmp/net-snmp_5.8.bb                  |   1 +
 2 files changed, 167 insertions(+)
 create mode 100644 meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch

Patch hide | download patch | download mbox

diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
new file mode 100644
index 000000000..99f02adb7
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
@@ -0,0 +1,166 @@ 
+From 76819d992fdd88e3beb08b79851c6c129da7bc7e Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche@acm.org>
+Date: Fri, 10 Jul 2020 10:48:41 +0800
+Subject: [PATCH] libsnmp, USM: Introduce a reference count in struct
+ usmStateReference
+
+This patch fixes https://sourceforge.net/p/net-snmp/bugs/2956/.
+
+Upstream-Status: Backport [https://github.com/net-snmp/net-snmp/commit/5f881d3bf24599b90d67a45cae7a3eb099cd71c9]
+CVE: CVE-2019-20892
+
+Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
+---
+ include/net-snmp/library/snmpusm.h |  1 +
+ snmplib/snmp_client.c              | 21 +++-------
+ snmplib/snmpusm.c                  | 65 +++++++++++++++++++++---------
+ 3 files changed, 51 insertions(+), 36 deletions(-)
+
+diff --git a/include/net-snmp/library/snmpusm.h b/include/net-snmp/library/snmpusm.h
+index 3f60787..87b31f3 100644
+--- a/include/net-snmp/library/snmpusm.h
++++ b/include/net-snmp/library/snmpusm.h
+@@ -43,6 +43,7 @@ extern          "C" {
+      * Structures.
+      */
+     struct usmStateReference {
++        int             refcnt;
+         char           *usr_name;
+         size_t          usr_name_length;
+         u_char         *usr_engine_id;
+diff --git a/snmplib/snmp_client.c b/snmplib/snmp_client.c
+index 2a46351..b2ea891 100644
+--- a/snmplib/snmp_client.c
++++ b/snmplib/snmp_client.c
+@@ -402,27 +402,16 @@ _clone_pdu_header(netsnmp_pdu *pdu)
+         return NULL;
+     }
+ 
+-    if (pdu->securityStateRef &&
+-        pdu->command == SNMP_MSG_TRAP2) {
+-
+-        ret = usm_clone_usmStateReference((struct usmStateReference *) pdu->securityStateRef,
+-                (struct usmStateReference **) &newpdu->securityStateRef );
+-
+-        if (ret)
+-        {
++    sptr = find_sec_mod(newpdu->securityModel);
++    if (sptr && sptr->pdu_clone) {
++        /* call security model if it needs to know about this */
++        ret = sptr->pdu_clone(pdu, newpdu);
++        if (ret) {
+             snmp_free_pdu(newpdu);
+             return NULL;
+         }
+     }
+ 
+-    if ((sptr = find_sec_mod(newpdu->securityModel)) != NULL &&
+-        sptr->pdu_clone != NULL) {
+-        /*
+-         * call security model if it needs to know about this 
+-         */
+-        (*sptr->pdu_clone) (pdu, newpdu);
+-    }
+-
+     return newpdu;
+ }
+ 
+diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
+index 3cfa126..4d8edad 100644
+--- a/snmplib/snmpusm.c
++++ b/snmplib/snmpusm.c
+@@ -285,39 +285,63 @@ free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
+ struct usmStateReference *
+ usm_malloc_usmStateReference(void)
+ {
+-    struct usmStateReference *retval = (struct usmStateReference *)
+-        calloc(1, sizeof(struct usmStateReference));
++    struct usmStateReference *retval;
++
++    retval = calloc(1, sizeof(struct usmStateReference));
++    if (retval)
++        retval->refcnt = 1;
+ 
+     return retval;
+ }                               /* end usm_malloc_usmStateReference() */
+ 
++static int
++usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
++{
++    struct usmStateReference *ref = pdu->securityStateRef;
++    struct usmStateReference **new_ref =
++        (struct usmStateReference **)&new_pdu->securityStateRef;
++    int ret = 0;
++
++    if (!ref)
++        return ret;
++
++    if (pdu->command == SNMP_MSG_TRAP2) {
++        netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
++        ret = usm_clone_usmStateReference(ref, new_ref);
++    } else {
++        netsnmp_assert(ref == *new_ref);
++        ref->refcnt++;
++    }
++
++    return ret;
++}
+ 
+ void
+ usm_free_usmStateReference(void *old)
+ {
+-    struct usmStateReference *old_ref = (struct usmStateReference *) old;
+-
+-    if (old_ref) {
++    struct usmStateReference *ref = old;
+ 
+-        SNMP_FREE(old_ref->usr_name);
+-        SNMP_FREE(old_ref->usr_engine_id);
+-        SNMP_FREE(old_ref->usr_auth_protocol);
+-        SNMP_FREE(old_ref->usr_priv_protocol);
+-
+-        if (old_ref->usr_auth_key) {
+-            SNMP_ZERO(old_ref->usr_auth_key, old_ref->usr_auth_key_length);
+-            SNMP_FREE(old_ref->usr_auth_key);
+-        }
+-        if (old_ref->usr_priv_key) {
+-            SNMP_ZERO(old_ref->usr_priv_key, old_ref->usr_priv_key_length);
+-            SNMP_FREE(old_ref->usr_priv_key);
+-        }
++    if (!ref)
++        return;
+ 
+-        SNMP_ZERO(old_ref, sizeof(*old_ref));
+-        SNMP_FREE(old_ref);
++    if (--ref->refcnt > 0)
++        return;
+ 
++    SNMP_FREE(ref->usr_name);
++    SNMP_FREE(ref->usr_engine_id);
++    SNMP_FREE(ref->usr_auth_protocol);
++    SNMP_FREE(ref->usr_priv_protocol);
++ 
++    if (ref->usr_auth_key_length && ref->usr_auth_key) {
++        SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
++        SNMP_FREE(ref->usr_auth_key);
++    }
++    if (ref->usr_priv_key_length && ref->usr_priv_key) {
++        SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
++        SNMP_FREE(ref->usr_priv_key);
+     }
+ 
++    SNMP_FREE(ref);
+ }                               /* end usm_free_usmStateReference() */
+ 
+ struct usmUser *
+@@ -3345,6 +3369,7 @@ init_usm(void)
+     def->encode_reverse = usm_secmod_rgenerate_out_msg;
+     def->encode_forward = usm_secmod_generate_out_msg;
+     def->decode = usm_secmod_process_in_msg;
++    def->pdu_clone = usm_clone;
+     def->pdu_free_state_ref = usm_free_usmStateReference;
+     def->session_setup = usm_session_init;
+     def->handle_report = usm_handle_report;
+-- 
+2.18.1
+
diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
index 192b6b506..c23dcd3cf 100644
--- a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
@@ -27,6 +27,7 @@  SRC_URI = "${SOURCEFORGE_MIRROR}/net-snmp/net-snmp-${PV}.tar.gz \
            file://reproducibility-have-printcap.patch \
            file://reproducibility-accept-configure-options-from-env.patch \
            file://0001-net-snmp-fix-compile-error-disable-des.patch \
+           file://0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch \
            "
 SRC_URI[md5sum] = "63bfc65fbb86cdb616598df1aff6458a"
 SRC_URI[sha256sum] = "b2fc3500840ebe532734c4786b0da4ef0a5f67e51ef4c86b3345d697e4976adf"

Comments

Khem Raj July 13, 2020, 5:07 p.m.
On 7/13/20 3:05 AM, wenlin.kang@windriver.com wrote:
> Fix CVE-2019-20892
> 
> Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
> ---
>   ...oduce-a-reference-count-in-struct-us.patch | 166 ++++++++++++++++++
>   .../net-snmp/net-snmp_5.8.bb                  |   1 +
>   2 files changed, 167 insertions(+)
>   create mode 100644 meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
> 
> diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
> new file mode 100644
> index 000000000..99f02adb7
> --- /dev/null
> +++ b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
> @@ -0,0 +1,166 @@
> +From 76819d992fdd88e3beb08b79851c6c129da7bc7e Mon Sep 17 00:00:00 2001
> +From: Bart Van Assche <bvanassche@acm.org>
> +Date: Fri, 10 Jul 2020 10:48:41 +0800
> +Subject: [PATCH] libsnmp, USM: Introduce a reference count in struct
> + usmStateReference
> +
> +This patch fixes https://sourceforge.net/p/net-snmp/bugs/2956/.
> +
> +Upstream-Status: Backport [https://github.com/net-snmp/net-snmp/commit/5f881d3bf24599b90d67a45cae7a3eb099cd71c9]
> +CVE: CVE-2019-20892

do we need this on master too ?

> +
> +Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
> +---
> + include/net-snmp/library/snmpusm.h |  1 +
> + snmplib/snmp_client.c              | 21 +++-------
> + snmplib/snmpusm.c                  | 65 +++++++++++++++++++++---------
> + 3 files changed, 51 insertions(+), 36 deletions(-)
> +
> +diff --git a/include/net-snmp/library/snmpusm.h b/include/net-snmp/library/snmpusm.h
> +index 3f60787..87b31f3 100644
> +--- a/include/net-snmp/library/snmpusm.h
> ++++ b/include/net-snmp/library/snmpusm.h
> +@@ -43,6 +43,7 @@ extern          "C" {
> +      * Structures.
> +      */
> +     struct usmStateReference {
> ++        int             refcnt;
> +         char           *usr_name;
> +         size_t          usr_name_length;
> +         u_char         *usr_engine_id;
> +diff --git a/snmplib/snmp_client.c b/snmplib/snmp_client.c
> +index 2a46351..b2ea891 100644
> +--- a/snmplib/snmp_client.c
> ++++ b/snmplib/snmp_client.c
> +@@ -402,27 +402,16 @@ _clone_pdu_header(netsnmp_pdu *pdu)
> +         return NULL;
> +     }
> +
> +-    if (pdu->securityStateRef &&
> +-        pdu->command == SNMP_MSG_TRAP2) {
> +-
> +-        ret = usm_clone_usmStateReference((struct usmStateReference *) pdu->securityStateRef,
> +-                (struct usmStateReference **) &newpdu->securityStateRef );
> +-
> +-        if (ret)
> +-        {
> ++    sptr = find_sec_mod(newpdu->securityModel);
> ++    if (sptr && sptr->pdu_clone) {
> ++        /* call security model if it needs to know about this */
> ++        ret = sptr->pdu_clone(pdu, newpdu);
> ++        if (ret) {
> +             snmp_free_pdu(newpdu);
> +             return NULL;
> +         }
> +     }
> +
> +-    if ((sptr = find_sec_mod(newpdu->securityModel)) != NULL &&
> +-        sptr->pdu_clone != NULL) {
> +-        /*
> +-         * call security model if it needs to know about this
> +-         */
> +-        (*sptr->pdu_clone) (pdu, newpdu);
> +-    }
> +-
> +     return newpdu;
> + }
> +
> +diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
> +index 3cfa126..4d8edad 100644
> +--- a/snmplib/snmpusm.c
> ++++ b/snmplib/snmpusm.c
> +@@ -285,39 +285,63 @@ free_enginetime_on_shutdown(int majorid, int minorid, void *serverarg,
> + struct usmStateReference *
> + usm_malloc_usmStateReference(void)
> + {
> +-    struct usmStateReference *retval = (struct usmStateReference *)
> +-        calloc(1, sizeof(struct usmStateReference));
> ++    struct usmStateReference *retval;
> ++
> ++    retval = calloc(1, sizeof(struct usmStateReference));
> ++    if (retval)
> ++        retval->refcnt = 1;
> +
> +     return retval;
> + }                               /* end usm_malloc_usmStateReference() */
> +
> ++static int
> ++usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
> ++{
> ++    struct usmStateReference *ref = pdu->securityStateRef;
> ++    struct usmStateReference **new_ref =
> ++        (struct usmStateReference **)&new_pdu->securityStateRef;
> ++    int ret = 0;
> ++
> ++    if (!ref)
> ++        return ret;
> ++
> ++    if (pdu->command == SNMP_MSG_TRAP2) {
> ++        netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
> ++        ret = usm_clone_usmStateReference(ref, new_ref);
> ++    } else {
> ++        netsnmp_assert(ref == *new_ref);
> ++        ref->refcnt++;
> ++    }
> ++
> ++    return ret;
> ++}
> +
> + void
> + usm_free_usmStateReference(void *old)
> + {
> +-    struct usmStateReference *old_ref = (struct usmStateReference *) old;
> +-
> +-    if (old_ref) {
> ++    struct usmStateReference *ref = old;
> +
> +-        SNMP_FREE(old_ref->usr_name);
> +-        SNMP_FREE(old_ref->usr_engine_id);
> +-        SNMP_FREE(old_ref->usr_auth_protocol);
> +-        SNMP_FREE(old_ref->usr_priv_protocol);
> +-
> +-        if (old_ref->usr_auth_key) {
> +-            SNMP_ZERO(old_ref->usr_auth_key, old_ref->usr_auth_key_length);
> +-            SNMP_FREE(old_ref->usr_auth_key);
> +-        }
> +-        if (old_ref->usr_priv_key) {
> +-            SNMP_ZERO(old_ref->usr_priv_key, old_ref->usr_priv_key_length);
> +-            SNMP_FREE(old_ref->usr_priv_key);
> +-        }
> ++    if (!ref)
> ++        return;
> +
> +-        SNMP_ZERO(old_ref, sizeof(*old_ref));
> +-        SNMP_FREE(old_ref);
> ++    if (--ref->refcnt > 0)
> ++        return;
> +
> ++    SNMP_FREE(ref->usr_name);
> ++    SNMP_FREE(ref->usr_engine_id);
> ++    SNMP_FREE(ref->usr_auth_protocol);
> ++    SNMP_FREE(ref->usr_priv_protocol);
> ++
> ++    if (ref->usr_auth_key_length && ref->usr_auth_key) {
> ++        SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
> ++        SNMP_FREE(ref->usr_auth_key);
> ++    }
> ++    if (ref->usr_priv_key_length && ref->usr_priv_key) {
> ++        SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
> ++        SNMP_FREE(ref->usr_priv_key);
> +     }
> +
> ++    SNMP_FREE(ref);
> + }                               /* end usm_free_usmStateReference() */
> +
> + struct usmUser *
> +@@ -3345,6 +3369,7 @@ init_usm(void)
> +     def->encode_reverse = usm_secmod_rgenerate_out_msg;
> +     def->encode_forward = usm_secmod_generate_out_msg;
> +     def->decode = usm_secmod_process_in_msg;
> ++    def->pdu_clone = usm_clone;
> +     def->pdu_free_state_ref = usm_free_usmStateReference;
> +     def->session_setup = usm_session_init;
> +     def->handle_report = usm_handle_report;
> +--
> +2.18.1
> +
> diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
> index 192b6b506..c23dcd3cf 100644
> --- a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
> +++ b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
> @@ -27,6 +27,7 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/net-snmp/net-snmp-${PV}.tar.gz \
>              file://reproducibility-have-printcap.patch \
>              file://reproducibility-accept-configure-options-from-env.patch \
>              file://0001-net-snmp-fix-compile-error-disable-des.patch \
> +           file://0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch \
>              "
>   SRC_URI[md5sum] = "63bfc65fbb86cdb616598df1aff6458a"
>   SRC_URI[sha256sum] = "b2fc3500840ebe532734c4786b0da4ef0a5f67e51ef4c86b3345d697e4976adf"
> 
> 
> 
>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#85763): https://lists.openembedded.org/g/openembedded-devel/message/85763
Mute This Topic: https://lists.openembedded.org/mt/75473865/3617530
Group Owner: openembedded-devel+owner@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub  [oe-patchwork@oe-patch.openembedded.org]
-=-=-=-=-=-=-=-=-=-=-=-
Wenlin Kang July 15, 2020, 7:40 a.m.
On 2020/7/14 上午1:07, Khem Raj wrote:
>
>
> On 7/13/20 3:05 AM, wenlin.kang@windriver.com wrote:
>> Fix CVE-2019-20892
>>
>> Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
>> ---
>>   ...oduce-a-reference-count-in-struct-us.patch | 166 ++++++++++++++++++
>>   .../net-snmp/net-snmp_5.8.bb                  |   1 +
>>   2 files changed, 167 insertions(+)
>>   create mode 100644 
>> meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
>>
>> diff --git 
>> a/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch 
>> b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch 
>>
>> new file mode 100644
>> index 000000000..99f02adb7
>> --- /dev/null
>> +++ 
>> b/meta-networking/recipes-protocols/net-snmp/net-snmp/0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch
>> @@ -0,0 +1,166 @@
>> +From 76819d992fdd88e3beb08b79851c6c129da7bc7e Mon Sep 17 00:00:00 2001
>> +From: Bart Van Assche <bvanassche@acm.org>
>> +Date: Fri, 10 Jul 2020 10:48:41 +0800
>> +Subject: [PATCH] libsnmp, USM: Introduce a reference count in struct
>> + usmStateReference
>> +
>> +This patch fixes https://sourceforge.net/p/net-snmp/bugs/2956/.
>> +
>> +Upstream-Status: Backport 
>> [https://github.com/net-snmp/net-snmp/commit/5f881d3bf24599b90d67a45cae7a3eb099cd71c9]
>> +CVE: CVE-2019-20892
>
> do we need this on master too ?


master has included this patch,  only zeus needs it.


commit 96a63b1ecf321c9a63880a963ed257086998133b
Author: Armin Kuster <akuster@mvista.com>
Date:   Fri Jun 26 16:14:10 2020 -0700

     net-snmp: Security fix CVE-2019-20892

     Source: net-snmp.org
     MR: 104509
     Type: Security Fix
     Disposition: Backport from 
https://github.com/net-snmp/net-snmp/commit/5f881d3bf24599b90d67a45cae7a3eb099cd71c9
     ChangeID: 206d822029d48d904864f23fd1b1af69dffc26c8
     Description:

     Fixes CVE-2019-20892 which affect net-snmp <= 5.8pre1

     Had to fix up some file do to later code restructioning.
     "int             refcnt;" addition was done in 
include/net-snmp/library/snmpusm.h

     Signed-off-by: Armin Kuster <akuster@mvista.com>
     Signed-off-by: Khem Raj <raj.khem@gmail.com>


>
>> +
>> +Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
>> +---
>> + include/net-snmp/library/snmpusm.h |  1 +
>> + snmplib/snmp_client.c              | 21 +++-------
>> + snmplib/snmpusm.c                  | 65 +++++++++++++++++++++---------
>> + 3 files changed, 51 insertions(+), 36 deletions(-)
>> +
>> +diff --git a/include/net-snmp/library/snmpusm.h 
>> b/include/net-snmp/library/snmpusm.h
>> +index 3f60787..87b31f3 100644
>> +--- a/include/net-snmp/library/snmpusm.h
>> ++++ b/include/net-snmp/library/snmpusm.h
>> +@@ -43,6 +43,7 @@ extern          "C" {
>> +      * Structures.
>> +      */
>> +     struct usmStateReference {
>> ++        int             refcnt;
>> +         char           *usr_name;
>> +         size_t          usr_name_length;
>> +         u_char         *usr_engine_id;
>> +diff --git a/snmplib/snmp_client.c b/snmplib/snmp_client.c
>> +index 2a46351..b2ea891 100644
>> +--- a/snmplib/snmp_client.c
>> ++++ b/snmplib/snmp_client.c
>> +@@ -402,27 +402,16 @@ _clone_pdu_header(netsnmp_pdu *pdu)
>> +         return NULL;
>> +     }
>> +
>> +-    if (pdu->securityStateRef &&
>> +-        pdu->command == SNMP_MSG_TRAP2) {
>> +-
>> +-        ret = usm_clone_usmStateReference((struct usmStateReference 
>> *) pdu->securityStateRef,
>> +-                (struct usmStateReference **) 
>> &newpdu->securityStateRef );
>> +-
>> +-        if (ret)
>> +-        {
>> ++    sptr = find_sec_mod(newpdu->securityModel);
>> ++    if (sptr && sptr->pdu_clone) {
>> ++        /* call security model if it needs to know about this */
>> ++        ret = sptr->pdu_clone(pdu, newpdu);
>> ++        if (ret) {
>> +             snmp_free_pdu(newpdu);
>> +             return NULL;
>> +         }
>> +     }
>> +
>> +-    if ((sptr = find_sec_mod(newpdu->securityModel)) != NULL &&
>> +-        sptr->pdu_clone != NULL) {
>> +-        /*
>> +-         * call security model if it needs to know about this
>> +-         */
>> +-        (*sptr->pdu_clone) (pdu, newpdu);
>> +-    }
>> +-
>> +     return newpdu;
>> + }
>> +
>> +diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
>> +index 3cfa126..4d8edad 100644
>> +--- a/snmplib/snmpusm.c
>> ++++ b/snmplib/snmpusm.c
>> +@@ -285,39 +285,63 @@ free_enginetime_on_shutdown(int majorid, int 
>> minorid, void *serverarg,
>> + struct usmStateReference *
>> + usm_malloc_usmStateReference(void)
>> + {
>> +-    struct usmStateReference *retval = (struct usmStateReference *)
>> +-        calloc(1, sizeof(struct usmStateReference));
>> ++    struct usmStateReference *retval;
>> ++
>> ++    retval = calloc(1, sizeof(struct usmStateReference));
>> ++    if (retval)
>> ++        retval->refcnt = 1;
>> +
>> +     return retval;
>> + }                               /* end 
>> usm_malloc_usmStateReference() */
>> +
>> ++static int
>> ++usm_clone(netsnmp_pdu *pdu, netsnmp_pdu *new_pdu)
>> ++{
>> ++    struct usmStateReference *ref = pdu->securityStateRef;
>> ++    struct usmStateReference **new_ref =
>> ++        (struct usmStateReference **)&new_pdu->securityStateRef;
>> ++    int ret = 0;
>> ++
>> ++    if (!ref)
>> ++        return ret;
>> ++
>> ++    if (pdu->command == SNMP_MSG_TRAP2) {
>> ++        netsnmp_assert(pdu->securityModel == SNMP_DEFAULT_SECMODEL);
>> ++        ret = usm_clone_usmStateReference(ref, new_ref);
>> ++    } else {
>> ++        netsnmp_assert(ref == *new_ref);
>> ++        ref->refcnt++;
>> ++    }
>> ++
>> ++    return ret;
>> ++}
>> +
>> + void
>> + usm_free_usmStateReference(void *old)
>> + {
>> +-    struct usmStateReference *old_ref = (struct usmStateReference 
>> *) old;
>> +-
>> +-    if (old_ref) {
>> ++    struct usmStateReference *ref = old;
>> +
>> +-        SNMP_FREE(old_ref->usr_name);
>> +-        SNMP_FREE(old_ref->usr_engine_id);
>> +-        SNMP_FREE(old_ref->usr_auth_protocol);
>> +-        SNMP_FREE(old_ref->usr_priv_protocol);
>> +-
>> +-        if (old_ref->usr_auth_key) {
>> +-            SNMP_ZERO(old_ref->usr_auth_key, 
>> old_ref->usr_auth_key_length);
>> +-            SNMP_FREE(old_ref->usr_auth_key);
>> +-        }
>> +-        if (old_ref->usr_priv_key) {
>> +-            SNMP_ZERO(old_ref->usr_priv_key, 
>> old_ref->usr_priv_key_length);
>> +-            SNMP_FREE(old_ref->usr_priv_key);
>> +-        }
>> ++    if (!ref)
>> ++        return;
>> +
>> +-        SNMP_ZERO(old_ref, sizeof(*old_ref));
>> +-        SNMP_FREE(old_ref);
>> ++    if (--ref->refcnt > 0)
>> ++        return;
>> +
>> ++    SNMP_FREE(ref->usr_name);
>> ++    SNMP_FREE(ref->usr_engine_id);
>> ++    SNMP_FREE(ref->usr_auth_protocol);
>> ++    SNMP_FREE(ref->usr_priv_protocol);
>> ++
>> ++    if (ref->usr_auth_key_length && ref->usr_auth_key) {
>> ++        SNMP_ZERO(ref->usr_auth_key, ref->usr_auth_key_length);
>> ++        SNMP_FREE(ref->usr_auth_key);
>> ++    }
>> ++    if (ref->usr_priv_key_length && ref->usr_priv_key) {
>> ++        SNMP_ZERO(ref->usr_priv_key, ref->usr_priv_key_length);
>> ++        SNMP_FREE(ref->usr_priv_key);
>> +     }
>> +
>> ++    SNMP_FREE(ref);
>> + }                               /* end usm_free_usmStateReference() */
>> +
>> + struct usmUser *
>> +@@ -3345,6 +3369,7 @@ init_usm(void)
>> +     def->encode_reverse = usm_secmod_rgenerate_out_msg;
>> +     def->encode_forward = usm_secmod_generate_out_msg;
>> +     def->decode = usm_secmod_process_in_msg;
>> ++    def->pdu_clone = usm_clone;
>> +     def->pdu_free_state_ref = usm_free_usmStateReference;
>> +     def->session_setup = usm_session_init;
>> +     def->handle_report = usm_handle_report;
>> +--
>> +2.18.1
>> +
>> diff --git 
>> a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb 
>> b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
>> index 192b6b506..c23dcd3cf 100644
>> --- a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
>> +++ b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.8.bb
>> @@ -27,6 +27,7 @@ SRC_URI = 
>> "${SOURCEFORGE_MIRROR}/net-snmp/net-snmp-${PV}.tar.gz \
>>              file://reproducibility-have-printcap.patch \
>> file://reproducibility-accept-configure-options-from-env.patch \
>> file://0001-net-snmp-fix-compile-error-disable-des.patch \
>> + 
>> file://0001-libsnmp-USM-Introduce-a-reference-count-in-struct-us.patch \
>>              "
>>   SRC_URI[md5sum] = "63bfc65fbb86cdb616598df1aff6458a"
>>   SRC_URI[sha256sum] = 
>> "b2fc3500840ebe532734c4786b0da4ef0a5f67e51ef4c86b3345d697e4976adf"
>>
>>
>> 
>>