Fix CVE-2019-20892
This commit is contained in:
parent
9474bf22ef
commit
51a1764e29
363
CVE-2019-20892-1.patch
Normal file
363
CVE-2019-20892-1.patch
Normal file
@ -0,0 +1,363 @@
|
||||
From adc9b71aba9168ec64149345ea37a1acc11875c6 Mon Sep 17 00:00:00 2001
|
||||
From: Sam Tannous <stannous@cumulusnetworks.com>
|
||||
Date: Wed, 10 Apr 2019 06:57:21 -0700
|
||||
Subject: [PATCH] snmpd: Avoid that snmpv3 bulkget errors result in a double
|
||||
free
|
||||
|
||||
See also https://sourceforge.net/p/net-snmp/bugs/2923/.
|
||||
See also https://sourceforge.net/p/net-snmp/patches/1388/.
|
||||
---
|
||||
agent/snmp_agent.c | 7 ++++++
|
||||
include/net-snmp/pdu_api.h | 2 ++
|
||||
snmplib/snmp_api.c | 11 ++++++++
|
||||
snmplib/snmpusm.c | 51 ++++++++------------------------------
|
||||
4 files changed, 31 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c
|
||||
index 26653f4e6..100c4d001 100644
|
||||
--- a/agent/snmp_agent.c
|
||||
+++ b/agent/snmp_agent.c
|
||||
@@ -1604,6 +1604,13 @@ free_agent_snmp_session(netsnmp_agent_session *asp)
|
||||
|
||||
DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p freed\n",
|
||||
asp, asp->reqinfo));
|
||||
+
|
||||
+ /* Clean up securityStateRef here to prevent a double free */
|
||||
+ if (asp->orig_pdu && asp->orig_pdu->securityStateRef)
|
||||
+ snmp_free_securityStateRef(asp->orig_pdu);
|
||||
+ if (asp->pdu && asp->pdu->securityStateRef)
|
||||
+ snmp_free_securityStateRef(asp->pdu);
|
||||
+
|
||||
if (asp->orig_pdu)
|
||||
snmp_free_pdu(asp->orig_pdu);
|
||||
if (asp->pdu)
|
||||
diff --git a/include/net-snmp/pdu_api.h b/include/net-snmp/pdu_api.h
|
||||
index 125595d9a..270aff054 100644
|
||||
--- a/include/net-snmp/pdu_api.h
|
||||
+++ b/include/net-snmp/pdu_api.h
|
||||
@@ -19,6 +19,8 @@ NETSNMP_IMPORT
|
||||
netsnmp_pdu *snmp_fix_pdu( netsnmp_pdu *pdu, int idx);
|
||||
NETSNMP_IMPORT
|
||||
void snmp_free_pdu( netsnmp_pdu *pdu);
|
||||
+NETSNMP_IMPORT
|
||||
+void snmp_free_securityStateRef( netsnmp_pdu *pdu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c
|
||||
index 554767a83..321a48f1b 100644
|
||||
--- a/snmplib/snmp_api.c
|
||||
+++ b/snmplib/snmp_api.c
|
||||
@@ -4028,6 +4028,17 @@ free_securityStateRef(netsnmp_pdu* pdu)
|
||||
pdu->securityStateRef = NULL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * This function is here to provide a separate call to
|
||||
+ * free the securityStateRef memory. This is needed to prevent
|
||||
+ * a double free if this memory is freed in snmp_free_pdu.
|
||||
+ */
|
||||
+void
|
||||
+snmp_free_securityStateRef(netsnmp_pdu* pdu)
|
||||
+{
|
||||
+ free_securityStateRef(pdu);
|
||||
+}
|
||||
+
|
||||
#define ERROR_STAT_LENGTH 11
|
||||
|
||||
int
|
||||
diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
|
||||
index 3cfa1267a..873bd890f 100644
|
||||
--- a/snmplib/snmpusm.c
|
||||
+++ b/snmplib/snmpusm.c
|
||||
@@ -299,16 +299,20 @@ usm_free_usmStateReference(void *old)
|
||||
|
||||
if (old_ref) {
|
||||
|
||||
- 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) {
|
||||
+ if (old_ref->usr_name_length)
|
||||
+ SNMP_FREE(old_ref->usr_name);
|
||||
+ if (old_ref->usr_engine_id_length)
|
||||
+ SNMP_FREE(old_ref->usr_engine_id);
|
||||
+ if (old_ref->usr_auth_protocol_length)
|
||||
+ SNMP_FREE(old_ref->usr_auth_protocol);
|
||||
+ if (old_ref->usr_auth_protocol_length)
|
||||
+ SNMP_FREE(old_ref->usr_priv_protocol);
|
||||
+
|
||||
+ if (old_ref->usr_auth_key_length && 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) {
|
||||
+ if (old_ref->usr_priv_key_length && 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);
|
||||
}
|
||||
@@ -1039,7 +1043,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
if ((user = usm_get_user(secEngineID, secEngineIDLen, secName))
|
||||
== NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
|
||||
DEBUGMSGTL(("usm", "Unknown User(%s)\n", secName));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_UNKNOWNSECURITYNAME;
|
||||
}
|
||||
|
||||
@@ -1091,7 +1094,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
thePrivProtocolLength) == 1) {
|
||||
DEBUGMSGTL(("usm", "Unsupported Security Level (%d)\n",
|
||||
theSecLevel));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
|
||||
}
|
||||
|
||||
@@ -1121,7 +1123,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
&msgAuthParmLen, &msgPrivParmLen, &otstlen,
|
||||
&seq_len, &msgSecParmLen) == -1) {
|
||||
DEBUGMSGTL(("usm", "Failed calculating offsets.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
|
||||
@@ -1143,7 +1144,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
ptr = *wholeMsg = globalData;
|
||||
if (theTotalLength > *wholeMsgLen) {
|
||||
DEBUGMSGTL(("usm", "Message won't fit in buffer.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1169,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
htonl(boots_uint), htonl(time_uint),
|
||||
&ptr[privParamsOffset]) == -1) {
|
||||
DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
}
|
||||
@@ -1185,7 +1184,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
&ptr[privParamsOffset])
|
||||
== -1)) {
|
||||
DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
}
|
||||
@@ -1198,7 +1196,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
&ptr[dataOffset], &encrypted_length)
|
||||
!= SNMP_ERR_NOERROR) {
|
||||
DEBUGMSGTL(("usm", "encryption error.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_ENCRYPTIONERROR;
|
||||
}
|
||||
#ifdef NETSNMP_ENABLE_TESTING_CODE
|
||||
@@ -1226,7 +1223,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
if ((encrypted_length != (theTotalLength - dataOffset))
|
||||
|| (salt_length != msgPrivParmLen)) {
|
||||
DEBUGMSGTL(("usm", "encryption length error.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_ENCRYPTIONERROR;
|
||||
}
|
||||
|
||||
@@ -1362,7 +1358,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
|
||||
if (temp_sig == NULL) {
|
||||
DEBUGMSGTL(("usm", "Out of memory.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1371,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
SNMP_ZERO(temp_sig, temp_sig_len);
|
||||
SNMP_FREE(temp_sig);
|
||||
DEBUGMSGTL(("usm", "Signing failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_AUTHENTICATIONFAILURE;
|
||||
}
|
||||
|
||||
@@ -1384,7 +1378,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
SNMP_ZERO(temp_sig, temp_sig_len);
|
||||
SNMP_FREE(temp_sig);
|
||||
DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_AUTHENTICATIONFAILURE;
|
||||
}
|
||||
|
||||
@@ -1398,7 +1391,6 @@ usm_generate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
/*
|
||||
* endif -- create keyed hash
|
||||
*/
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
|
||||
DEBUGMSGTL(("usm", "USM processing completed.\n"));
|
||||
|
||||
@@ -1548,7 +1540,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
if ((user = usm_get_user(secEngineID, secEngineIDLen, secName))
|
||||
== NULL && secLevel != SNMP_SEC_LEVEL_NOAUTH) {
|
||||
DEBUGMSGTL(("usm", "Unknown User\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_UNKNOWNSECURITYNAME;
|
||||
}
|
||||
|
||||
@@ -1601,7 +1592,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGMSGTL(("usm", "Unsupported Security Level or type (%d)\n",
|
||||
theSecLevel));
|
||||
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL;
|
||||
}
|
||||
|
||||
@@ -1636,7 +1626,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGMSGTL(("usm",
|
||||
"couldn't malloc %d bytes for encrypted PDU\n",
|
||||
(int)ciphertextlen));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_MALLOC;
|
||||
}
|
||||
|
||||
@@ -1652,7 +1641,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
htonl(boots_uint), htonl(time_uint),
|
||||
iv) == -1) {
|
||||
DEBUGMSGTL(("usm", "Can't set AES iv.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
SNMP_FREE(ciphertext);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
@@ -1667,7 +1655,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
thePrivKeyLength - 8,
|
||||
iv) == -1)) {
|
||||
DEBUGMSGTL(("usm", "Can't set DES-CBC salt.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
SNMP_FREE(ciphertext);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
@@ -1686,7 +1673,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
scopedPdu, scopedPduLen,
|
||||
ciphertext, &ciphertextlen) != SNMP_ERR_NOERROR) {
|
||||
DEBUGMSGTL(("usm", "encryption error.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
SNMP_FREE(ciphertext);
|
||||
return SNMPERR_USM_ENCRYPTIONERROR;
|
||||
}
|
||||
@@ -1703,7 +1689,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
ciphertext, ciphertextlen);
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "Encryption failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
SNMP_FREE(ciphertext);
|
||||
return SNMPERR_USM_ENCRYPTIONERROR;
|
||||
}
|
||||
@@ -1743,7 +1728,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGINDENTLESS();
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building privParams failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1766,7 +1750,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGINDENTLESS();
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building authParams failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1789,7 +1772,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGINDENTLESS();
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building authParams failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1805,7 +1787,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm",
|
||||
"building msgAuthoritativeEngineTime failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1821,7 +1802,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm",
|
||||
"building msgAuthoritativeEngineBoots failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1833,7 +1813,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
DEBUGINDENTLESS();
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building msgAuthoritativeEngineID failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1846,7 +1825,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
*offset - sp_offset);
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building usm security parameters failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1860,7 +1838,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building msgSecurityParameters failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1870,7 +1847,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
while ((*wholeMsgLen - *offset) < globalDataLen) {
|
||||
if (!asn_realloc(wholeMsg, wholeMsgLen)) {
|
||||
DEBUGMSGTL(("usm", "building global data failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
}
|
||||
@@ -1886,7 +1862,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
ASN_CONSTRUCTOR), *offset);
|
||||
if (rc == 0) {
|
||||
DEBUGMSGTL(("usm", "building master packet sequence failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_TOO_LONG;
|
||||
}
|
||||
|
||||
@@ -1904,7 +1879,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
|
||||
if (temp_sig == NULL) {
|
||||
DEBUGMSGTL(("usm", "Out of memory.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_GENERICERROR;
|
||||
}
|
||||
|
||||
@@ -1915,14 +1889,12 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
!= SNMP_ERR_NOERROR) {
|
||||
SNMP_FREE(temp_sig);
|
||||
DEBUGMSGTL(("usm", "Signing failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_AUTHENTICATIONFAILURE;
|
||||
}
|
||||
|
||||
if (temp_sig_len != msgAuthParmLen) {
|
||||
SNMP_FREE(temp_sig);
|
||||
DEBUGMSGTL(("usm", "Signing lengths failed.\n"));
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
return SNMPERR_USM_AUTHENTICATIONFAILURE;
|
||||
}
|
||||
|
||||
@@ -1933,7 +1905,6 @@ usm_rgenerate_out_msg(int msgProcModel, /* (UNUSED) */
|
||||
/*
|
||||
* endif -- create keyed hash
|
||||
*/
|
||||
- usm_free_usmStateReference(secStateRef);
|
||||
DEBUGMSGTL(("usm", "USM processing completed.\n"));
|
||||
return SNMPERR_SUCCESS;
|
||||
} /* end usm_rgenerate_out_msg() */
|
||||
89
CVE-2019-20892-2.patch
Normal file
89
CVE-2019-20892-2.patch
Normal file
@ -0,0 +1,89 @@
|
||||
From 92ccd5a82a019fbfa835cc8ab2294cf0ca48c8f2 Mon Sep 17 00:00:00 2001
|
||||
From: Bart Van Assche <bvanassche@acm.org>
|
||||
Date: Sat, 25 May 2019 16:33:31 +0200
|
||||
Subject: [PATCH] libsnmp: Move the securityStateRef check into
|
||||
free_securityStateRef()
|
||||
|
||||
Instead of making each free_securityStateRef() caller check the
|
||||
securityStateRef pointer, move that check into free_securityStateRef().
|
||||
---
|
||||
agent/snmp_agent.c | 4 ++--
|
||||
snmplib/snmp_api.c | 21 ++++++++++-----------
|
||||
2 files changed, 12 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c
|
||||
index 9d2355e33..b1881c96e 100644
|
||||
--- a/agent/snmp_agent.c
|
||||
+++ b/agent/snmp_agent.c
|
||||
@@ -1606,9 +1606,9 @@ free_agent_snmp_session(netsnmp_agent_session *asp)
|
||||
asp, asp->reqinfo));
|
||||
|
||||
/* Clean up securityStateRef here to prevent a double free */
|
||||
- if (asp->orig_pdu && asp->orig_pdu->securityStateRef)
|
||||
+ if (asp->orig_pdu)
|
||||
snmp_free_securityStateRef(asp->orig_pdu);
|
||||
- if (asp->pdu && asp->pdu->securityStateRef)
|
||||
+ if (asp->pdu)
|
||||
snmp_free_securityStateRef(asp->pdu);
|
||||
|
||||
if (asp->orig_pdu)
|
||||
diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c
|
||||
index 36ab2d2d8..7922ea794 100644
|
||||
--- a/snmplib/snmp_api.c
|
||||
+++ b/snmplib/snmp_api.c
|
||||
@@ -4020,7 +4020,12 @@ snmpv3_parse(netsnmp_pdu *pdu,
|
||||
static void
|
||||
free_securityStateRef(netsnmp_pdu* pdu)
|
||||
{
|
||||
- struct snmp_secmod_def *sptr = find_sec_mod(pdu->securityModel);
|
||||
+ struct snmp_secmod_def *sptr;
|
||||
+
|
||||
+ if (!pdu->securityStateRef)
|
||||
+ return;
|
||||
+
|
||||
+ sptr = find_sec_mod(pdu->securityModel);
|
||||
if (sptr) {
|
||||
if (sptr->pdu_free_state_ref) {
|
||||
(*sptr->pdu_free_state_ref) (pdu->securityStateRef);
|
||||
@@ -4142,9 +4147,7 @@ snmpv3_make_report(netsnmp_pdu *pdu, int error)
|
||||
* FIX - yes they should but USM needs to follow new EoP to determine
|
||||
* which cached values to use
|
||||
*/
|
||||
- if (pdu->securityStateRef) {
|
||||
- free_securityStateRef(pdu);
|
||||
- }
|
||||
+ free_securityStateRef(pdu);
|
||||
|
||||
if (error == SNMPERR_USM_NOTINTIMEWINDOW) {
|
||||
pdu->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
|
||||
@@ -5658,9 +5661,7 @@ _sess_process_packet_parse_pdu(void *sessp, netsnmp_session * sp,
|
||||
/*
|
||||
* Call the security model to free any securityStateRef supplied w/ msg.
|
||||
*/
|
||||
- if (pdu->securityStateRef != NULL) {
|
||||
- free_securityStateRef(pdu);
|
||||
- }
|
||||
+ free_securityStateRef(pdu);
|
||||
snmp_free_pdu(pdu);
|
||||
return NULL;
|
||||
}
|
||||
@@ -5698,9 +5699,7 @@ _sess_process_packet_handle_pdu(void *sessp, netsnmp_session * sp,
|
||||
/*
|
||||
* Call USM to free any securityStateRef supplied with the message.
|
||||
*/
|
||||
- if (pdu->securityStateRef) {
|
||||
- free_securityStateRef(pdu);
|
||||
- }
|
||||
+ free_securityStateRef(pdu);
|
||||
|
||||
for (rp = isp->requests; rp; orp = rp, rp = rp->next_request) {
|
||||
snmp_callback callback;
|
||||
@@ -5845,7 +5844,7 @@ _sess_process_packet_handle_pdu(void *sessp, netsnmp_session * sp,
|
||||
/*
|
||||
* Call USM to free any securityStateRef supplied with the message.
|
||||
*/
|
||||
- if (pdu->securityStateRef && pdu->command == SNMP_MSG_TRAP2)
|
||||
+ if (pdu->command == SNMP_MSG_TRAP2)
|
||||
free_securityStateRef(pdu);
|
||||
|
||||
if (!handled) {
|
||||
25
CVE-2019-20892-3.patch
Normal file
25
CVE-2019-20892-3.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 7384a8b550d4ed4a00e41b72229cfcc124926b06 Mon Sep 17 00:00:00 2001
|
||||
From: Ming Chen <ming0903@users.sourceforge.net>
|
||||
Date: Wed, 5 Jun 2019 19:58:44 -0700
|
||||
Subject: [PATCH] libsnmp: Fix usm_free_usmStateReference()
|
||||
|
||||
See also https://sourceforge.net/p/net-snmp/bugs/2923/.
|
||||
|
||||
Fixes: adc9b71aba91 ("snmpd: Avoid that snmpv3 bulkget errors result in a double free")
|
||||
---
|
||||
snmplib/snmpusm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
|
||||
index ed7dc2e59..90c485c3c 100644
|
||||
--- a/snmplib/snmpusm.c
|
||||
+++ b/snmplib/snmpusm.c
|
||||
@@ -305,7 +305,7 @@ usm_free_usmStateReference(void *old)
|
||||
SNMP_FREE(old_ref->usr_engine_id);
|
||||
if (old_ref->usr_auth_protocol_length)
|
||||
SNMP_FREE(old_ref->usr_auth_protocol);
|
||||
- if (old_ref->usr_auth_protocol_length)
|
||||
+ if (old_ref->usr_priv_protocol_length)
|
||||
SNMP_FREE(old_ref->usr_priv_protocol);
|
||||
|
||||
if (old_ref->usr_auth_key_length && old_ref->usr_auth_key) {
|
||||
68
CVE-2019-20892-4.patch
Normal file
68
CVE-2019-20892-4.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 39381c4d20dd8042870c28ae3b0c16291e50b705 Mon Sep 17 00:00:00 2001
|
||||
From: Bart Van Assche <bvanassche@acm.org>
|
||||
Date: Tue, 23 Jul 2019 10:52:28 -0700
|
||||
Subject: [PATCH] libsnmp: Unexport struct usmStateReference
|
||||
|
||||
Certain snmpd crashes can only be fixed by introducing a reference
|
||||
count in struct usmStateReference. Unexport that structure such that
|
||||
changing it does not affect the ABI.
|
||||
---
|
||||
include/net-snmp/library/snmpusm.h | 17 +----------------
|
||||
snmplib/snmpusm.c | 16 ++++++++++++++++
|
||||
2 files changed, 17 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/include/net-snmp/library/snmpusm.h b/include/net-snmp/library/snmpusm.h
|
||||
index 3f6078799..49061d8b1 100644
|
||||
--- a/include/net-snmp/library/snmpusm.h
|
||||
+++ b/include/net-snmp/library/snmpusm.h
|
||||
@@ -42,22 +42,7 @@ extern "C" {
|
||||
/*
|
||||
* Structures.
|
||||
*/
|
||||
- struct usmStateReference {
|
||||
- char *usr_name;
|
||||
- size_t usr_name_length;
|
||||
- u_char *usr_engine_id;
|
||||
- size_t usr_engine_id_length;
|
||||
- oid *usr_auth_protocol;
|
||||
- size_t usr_auth_protocol_length;
|
||||
- u_char *usr_auth_key;
|
||||
- size_t usr_auth_key_length;
|
||||
- oid *usr_priv_protocol;
|
||||
- size_t usr_priv_protocol_length;
|
||||
- u_char *usr_priv_key;
|
||||
- size_t usr_priv_key_length;
|
||||
- u_int usr_sec_level;
|
||||
- };
|
||||
-
|
||||
+ struct usmStateReference;
|
||||
|
||||
/*
|
||||
* struct usmUser: a structure to represent a given user in a list
|
||||
diff --git a/snmplib/snmpusm.c b/snmplib/snmpusm.c
|
||||
index ae2d16906..917865267 100644
|
||||
--- a/snmplib/snmpusm.c
|
||||
+++ b/snmplib/snmpusm.c
|
||||
@@ -84,6 +84,22 @@ netsnmp_feature_child_of(usm_support, usm_all)
|
||||
|
||||
netsnmp_feature_require(usm_support)
|
||||
|
||||
+struct usmStateReference {
|
||||
+ char *usr_name;
|
||||
+ size_t usr_name_length;
|
||||
+ u_char *usr_engine_id;
|
||||
+ size_t usr_engine_id_length;
|
||||
+ oid *usr_auth_protocol;
|
||||
+ size_t usr_auth_protocol_length;
|
||||
+ u_char *usr_auth_key;
|
||||
+ size_t usr_auth_key_length;
|
||||
+ oid *usr_priv_protocol;
|
||||
+ size_t usr_priv_protocol_length;
|
||||
+ u_char *usr_priv_key;
|
||||
+ size_t usr_priv_key_length;
|
||||
+ u_int usr_sec_level;
|
||||
+};
|
||||
+
|
||||
oid usmNoAuthProtocol[10] = { NETSNMP_USMAUTH_BASE_OID,
|
||||
NETSNMP_USMAUTH_NOAUTH };
|
||||
#ifndef NETSNMP_DISABLE_MD5
|
||||
161
CVE-2019-20892-5.patch
Normal file
161
CVE-2019-20892-5.patch
Normal file
@ -0,0 +1,161 @@
|
||||
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/.
|
||||
---
|
||||
snmplib/snmp_client.c | 22 +++----------
|
||||
snmplib/snmpusm.c | 73 ++++++++++++++++++++++++++++---------------
|
||||
2 files changed, 53 insertions(+), 42 deletions(-)
|
||||
|
||||
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 c4e11b3..9e912c1 100644
|
||||
--- a/snmplib/snmpusm.c
|
||||
+++ b/snmplib/snmpusm.c
|
||||
@@ -85,6 +85,7 @@ netsnmp_feature_child_of(usm_support, usm_all)
|
||||
netsnmp_feature_require(usm_support)
|
||||
|
||||
struct usmStateReference {
|
||||
+ int refcnt;
|
||||
char *usr_name;
|
||||
size_t usr_name_length;
|
||||
u_char *usr_engine_id;
|
||||
@@ -301,43 +302,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) {
|
||||
-
|
||||
- if (old_ref->usr_name_length)
|
||||
- SNMP_FREE(old_ref->usr_name);
|
||||
- if (old_ref->usr_engine_id_length)
|
||||
- SNMP_FREE(old_ref->usr_engine_id);
|
||||
- if (old_ref->usr_auth_protocol_length)
|
||||
- SNMP_FREE(old_ref->usr_auth_protocol);
|
||||
- if (old_ref->usr_priv_protocol_length)
|
||||
- SNMP_FREE(old_ref->usr_priv_protocol);
|
||||
-
|
||||
- if (old_ref->usr_auth_key_length && 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_length && 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);
|
||||
- }
|
||||
+ struct usmStateReference *ref = old;
|
||||
+
|
||||
+ if (!ref)
|
||||
+ return;
|
||||
+
|
||||
+ if (--ref->refcnt > 0)
|
||||
+ return;
|
||||
|
||||
- SNMP_ZERO(old_ref, sizeof(*old_ref));
|
||||
- SNMP_FREE(old_ref);
|
||||
+ 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 *
|
||||
@@ -3332,6 +3353,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;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
106
CVE-2019-20892-6.patch
Normal file
106
CVE-2019-20892-6.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From 87bd90d04f20dd3f73e3e7e631a442ccd419b9d3 Mon Sep 17 00:00:00 2001
|
||||
From: Bart Van Assche <bvanassche@acm.org>
|
||||
Date: Tue, 13 Aug 2019 20:54:23 -0700
|
||||
Subject: [PATCH] libsnmp: Move the free_securityStateRef() call into
|
||||
snmp_free_pdu()
|
||||
|
||||
This patch fixes a memory leak that was introduced in commit 5f881d3bf245
|
||||
("libsnmp, USM: Introduce a reference count in struct usmStateReference").
|
||||
|
||||
This patch partially reverts commit adc9b71aba91 ("snmpd: Avoid that snmpv3
|
||||
bulkget errors result in a double free").
|
||||
|
||||
See also https://sourceforge.net/p/net-snmp/bugs/2938/.
|
||||
---
|
||||
agent/snmp_agent.c| 6 ------
|
||||
include/net-snmp/pdu_api.h | 2 --
|
||||
snmplib/snmp_api.c| 23 ++---------------------
|
||||
3 files changed, 2 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c
|
||||
index 0a1e263..25350e6 100644
|
||||
--- a/agent/snmp_agent.c
|
||||
+++ b/agent/snmp_agent.c
|
||||
@@ -1605,12 +1605,6 @@ free_agent_snmp_session(netsnmp_agent_session *asp)
|
||||
DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p freed\n",
|
||||
asp, asp->reqinfo));
|
||||
|
||||
- /* Clean up securityStateRef here to prevent a double free */
|
||||
- if (asp->orig_pdu)
|
||||
- snmp_free_securityStateRef(asp->orig_pdu);
|
||||
- if (asp->pdu)
|
||||
- snmp_free_securityStateRef(asp->pdu);
|
||||
-
|
||||
if (asp->orig_pdu)
|
||||
snmp_free_pdu(asp->orig_pdu);
|
||||
if (asp->pdu)
|
||||
diff --git a/include/net-snmp/pdu_api.h b/include/net-snmp/pdu_api.h
|
||||
index 270aff0..125595d 100644
|
||||
--- a/include/net-snmp/pdu_api.h
|
||||
+++ b/include/net-snmp/pdu_api.h
|
||||
@@ -19,8 +19,6 @@ NETSNMP_IMPORT
|
||||
netsnmp_pdu *snmp_fix_pdu( netsnmp_pdu *pdu, int idx);
|
||||
NETSNMP_IMPORT
|
||||
void snmp_free_pdu( netsnmp_pdu *pdu);
|
||||
-NETSNMP_IMPORT
|
||||
-void snmp_free_securityStateRef( netsnmp_pdu *pdu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c
|
||||
index e14ae6f..3e57a55 100644
|
||||
--- a/snmplib/snmp_api.c
|
||||
+++ b/snmplib/snmp_api.c
|
||||
@@ -4033,17 +4033,6 @@ free_securityStateRef(netsnmp_pdu* pdu)
|
||||
pdu->securityStateRef = NULL;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * This function is here to provide a separate call to
|
||||
- * free the securityStateRef memory. This is needed to prevent
|
||||
- * a double free if this memory is freed in snmp_free_pdu.
|
||||
- */
|
||||
-void
|
||||
-snmp_free_securityStateRef(netsnmp_pdu* pdu)
|
||||
-{
|
||||
- free_securityStateRef(pdu);
|
||||
-}
|
||||
-
|
||||
#define ERROR_STAT_LENGTH 11
|
||||
|
||||
int
|
||||
@@ -5470,6 +5459,8 @@ snmp_free_pdu(netsnmp_pdu *pdu)
|
||||
if (!pdu)
|
||||
return;
|
||||
|
||||
+ free_securityStateRef(pdu);
|
||||
+
|
||||
/*
|
||||
* If the command field is empty, that probably indicates
|
||||
* that this PDU structure has already been freed.
|
||||
@@ -5644,10 +5635,6 @@ _sess_process_packet_parse_pdu(void *sessp, netsnmp_session * sp,
|
||||
}
|
||||
|
||||
if (ret != SNMP_ERR_NOERROR) {
|
||||
- /*
|
||||
- * Call the security model to free any securityStateRef supplied w/ msg.
|
||||
- */
|
||||
- free_securityStateRef(pdu);
|
||||
snmp_free_pdu(pdu);
|
||||
return NULL;
|
||||
}
|
||||
@@ -5819,12 +5806,6 @@ _sess_process_packet_handle_pdu(void *sessp, netsnmp_session * sp,
|
||||
}
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Call USM to free any securityStateRef supplied with the message.
|
||||
- */
|
||||
- if (pdu->command == SNMP_MSG_TRAP2)
|
||||
- free_securityStateRef(pdu);
|
||||
-
|
||||
if (!handled) {
|
||||
if (sp->flags & SNMP_FLAGS_SHARED_SOCKET)
|
||||
return -2;
|
||||
--
|
||||
1.8.3.1
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
Name: net-snmp
|
||||
Version: 5.8
|
||||
Release: 9
|
||||
Release: 10
|
||||
Epoch: 1
|
||||
Summary: SNMP Daemon
|
||||
License: BSD
|
||||
@ -32,10 +32,16 @@ Patch9: net-snmp-5.8-Remove-U64-typedef.patch
|
||||
Patch10: net-snmp-5.8-libnetsnmptrapd-against-MYSQL_LIBS.patch
|
||||
Patch11: net-snmp-5.7.3-iterator-fix.patch
|
||||
Patch12: net-snmp-5.8-autofs-skip.patch
|
||||
Patch101: net-snmp-5.8-modern-rpm-api.patch
|
||||
Patch102: net-snmp-5.8-python3.patch
|
||||
Patch13: net-snmp-5.8-modern-rpm-api.patch
|
||||
Patch14: net-snmp-5.8-python3.patch
|
||||
|
||||
Patch6000: avoid-triggering-undefined-shift-left.patch
|
||||
Patch15: avoid-triggering-undefined-shift-left.patch
|
||||
Patch16: CVE-2019-20892-1.patch
|
||||
Patch17: CVE-2019-20892-2.patch
|
||||
Patch18: CVE-2019-20892-3.patch
|
||||
Patch19: CVE-2019-20892-4.patch
|
||||
Patch20: CVE-2019-20892-5.patch
|
||||
Patch21: CVE-2019-20892-6.patch
|
||||
|
||||
%{?systemd_requires}
|
||||
BuildRequires: systemd gcc openssl-devel bzip2-devel elfutils-devel libselinux-devel
|
||||
@ -315,6 +321,12 @@ LD_LIBRARY_PATH=%{buildroot}/%{_libdir} make test
|
||||
%{_mandir}/man1/fixproc*
|
||||
|
||||
%changelog
|
||||
* Thu Jul 09 2020 zhouyihang <zhouyihang3@huawei.com> - 5.8-10
|
||||
- Type:cves
|
||||
- ID:CVE-2019-20892
|
||||
- SUG:NA
|
||||
- DESC: Fix CVE-2019-20892
|
||||
|
||||
* Fri Jun 19 2020 gaihuiying <gaihuiying1@huawei.com> - 5.8-9
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user