| From 5f881d3bf24599b90d67a45cae7a3eb099cd71c9 Mon Sep 17 00:00:00 2001 |
| From: Bart Van Assche <bvanassche@acm.org> |
| Date: Sat, 27 Jul 2019 19:34:09 -0700 |
| 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 |
| [ak: fixup for 5.8 context, changes to library/snmpusm.h] |
| |
| CVE: CVE-2019-20892 |
| |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| Signed-off-by: Mingde (Matthew) Zeng <matthew.zeng@windriver.com> |
| |
| --- |
| snmplib/snmp_client.c | 22 +++---------- |
| snmplib/snmpusm.c | 73 ++++++++++++++++++++++++++++--------------- |
| 2 files changed, 53 insertions(+), 42 deletions(-) |
| |
| Index: net-snmp-5.8/snmplib/snmpusm.c |
| =================================================================== |
| --- net-snmp-5.8.orig/snmplib/snmpusm.c |
| +++ net-snmp-5.8/snmplib/snmpusm.c |
| @@ -285,12 +285,35 @@ free_enginetime_on_shutdown(int majorid, |
| 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) |
| @@ -3345,6 +3368,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; |
| Index: net-snmp-5.8/snmplib/snmp_client.c |
| =================================================================== |
| --- net-snmp-5.8.orig/snmplib/snmp_client.c |
| +++ net-snmp-5.8/snmplib/snmp_client.c |
| @@ -402,27 +402,15 @@ _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; |
| } |
| |
| Index: net-snmp-5.8/include/net-snmp/library/snmpusm.h |
| =================================================================== |
| --- net-snmp-5.8.orig/include/net-snmp/library/snmpusm.h |
| +++ net-snmp-5.8/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; |