diff --git a/net-snmp-5.5-agentx-disconnect-crash.patch b/net-snmp-5.5-agentx-disconnect-crash.patch new file mode 100644 index 0000000..b3b47be --- /dev/null +++ b/net-snmp-5.5-agentx-disconnect-crash.patch @@ -0,0 +1,270 @@ +955511 - net-snmpd crash on time out +969061 - net-snmpd crash on time out +1038011 - net-snmp: snmpd crashes/hangs when AgentX subagent times-out + +Based on usptream commit 793d596838ff7cb48a73b675d62897c56c9e62df, +heavily backported to net-snmp-5.5 + +diff -up net-snmp-5.7.2/agent/mibgroup/agentx/master_admin.c.disconnect-crash net-snmp-5.7.2/agent/mibgroup/agentx/master_admin.c +--- net-snmp-5.7.2/agent/mibgroup/agentx/master_admin.c.disconnect-crash 2013-07-03 15:26:35.884813210 +0200 ++++ net-snmp-5.7.2/agent/mibgroup/agentx/master_admin.c 2013-07-03 15:26:35.908813135 +0200 +@@ -158,6 +158,7 @@ close_agentx_session(netsnmp_session * s + for (sp = session->subsession; sp != NULL; sp = sp->next) { + + if (sp->sessid == sessid) { ++ netsnmp_remove_delegated_requests_for_session(sp); + unregister_mibs_by_session(sp); + unregister_index_by_session(sp); + unregister_sysORTable_by_session(sp); +diff -up net-snmp-5.7.2/agent/mibgroup/agentx/master.c.disconnect-crash net-snmp-5.7.2/agent/mibgroup/agentx/master.c +--- net-snmp-5.7.2/agent/mibgroup/agentx/master.c.disconnect-crash 2013-07-03 15:26:35.000000000 +0200 ++++ net-snmp-5.7.2/agent/mibgroup/agentx/master.c 2013-07-03 15:29:00.644362208 +0200 +@@ -222,7 +222,7 @@ agentx_got_response(int operation, + /* response is too late, free the cache */ + if (magic) + netsnmp_free_delegated_cache((netsnmp_delegated_cache*) magic); +- return 0; ++ return 1; + } + requests = cache->requests; + +diff -up net-snmp-5.7.2/agent/snmp_agent.c.disconnect-crash net-snmp-5.7.2/agent/snmp_agent.c +--- net-snmp-5.7.2/agent/snmp_agent.c.disconnect-crash 2013-07-03 15:26:35.893813182 +0200 ++++ net-snmp-5.7.2/agent/snmp_agent.c 2013-07-03 15:28:28.979460861 +0200 +@@ -1446,6 +1446,7 @@ free_agent_snmp_session(netsnmp_agent_se + netsnmp_free_cachemap(asp->cache_store); + asp->cache_store = NULL; + } ++ agent_snmp_session_release_cancelled(asp); + SNMP_FREE(asp); + } + +@@ -1457,6 +1458,11 @@ netsnmp_check_for_delegated(netsnmp_agen + + if (NULL == asp->treecache) + return 0; ++ ++ if (agent_snmp_session_is_cancelled(asp)) { ++ printf("request %p cancelled\n", asp); ++ return 0; ++ } + + for (i = 0; i <= asp->treecache_num; i++) { + for (request = asp->treecache[i].requests_begin; request; +@@ -1535,39 +1541,48 @@ int + netsnmp_remove_delegated_requests_for_session(netsnmp_session *sess) + { + netsnmp_agent_session *asp; +- int count = 0; ++ int total_count = 0; + + for (asp = agent_delegated_list; asp; asp = asp->next) { + /* + * check each request + */ ++ int i; ++ int count = 0; + netsnmp_request_info *request; +- for(request = asp->requests; request; request = request->next) { +- /* +- * check session +- */ +- netsnmp_assert(NULL!=request->subtree); +- if(request->subtree->session != sess) +- continue; ++ for (i = 0; i <= asp->treecache_num; i++) { ++ for (request = asp->treecache[i].requests_begin; request; ++ request = request->next) { ++ /* ++ * check session ++ */ ++ netsnmp_assert(NULL!=request->subtree); ++ if(request->subtree->session != sess) ++ continue; + +- /* +- * matched! mark request as done +- */ +- netsnmp_request_set_error(request, SNMP_ERR_GENERR); +- ++count; ++ /* ++ * matched! mark request as done ++ */ ++ netsnmp_request_set_error(request, SNMP_ERR_GENERR); ++ ++count; ++ } ++ } ++ if (count) { ++ agent_snmp_session_mark_cancelled(asp); ++ total_count += count; + } + } + + /* + * if we found any, that request may be finished now + */ +- if(count) { ++ if(total_count) { + DEBUGMSGTL(("snmp_agent", "removed %d delegated request(s) for session " +- "%8p\n", count, sess)); +- netsnmp_check_outstanding_agent_requests(); ++ "%8p\n", total_count, sess)); ++ netsnmp_check_delegated_requests(); + } + +- return count; ++ return total_count; + } + + int +@@ -2739,19 +2754,11 @@ handle_var_requests(netsnmp_agent_sessio + return final_status; + } + +-/* +- * loop through our sessions known delegated sessions and check to see +- * if they've completed yet. If there are no more delegated sessions, +- * check for and process any queued requests +- */ + void +-netsnmp_check_outstanding_agent_requests(void) ++netsnmp_check_delegated_requests(void) + { + netsnmp_agent_session *asp, *prev_asp = NULL, *next_asp = NULL; + +- /* +- * deal with delegated requests +- */ + for (asp = agent_delegated_list; asp; asp = next_asp) { + next_asp = asp->next; /* save in case we clean up asp */ + if (!netsnmp_check_for_delegated(asp)) { +@@ -2790,6 +2797,22 @@ netsnmp_check_outstanding_agent_requests + prev_asp = asp; + } + } ++} ++ ++/* ++ * loop through our sessions known delegated sessions and check to see ++ * if they've completed yet. If there are no more delegated sessions, ++ * check for and process any queued requests ++ */ ++void ++netsnmp_check_outstanding_agent_requests(void) ++{ ++ netsnmp_agent_session *asp; ++ ++ /* ++ * deal with delegated requests ++ */ ++ netsnmp_check_delegated_requests(); + + /* + * if we are processing a set and there are more delegated +@@ -2819,7 +2842,8 @@ netsnmp_check_outstanding_agent_requests + + netsnmp_processing_set = netsnmp_agent_queued_list; + DEBUGMSGTL(("snmp_agent", "SET request remains queued while " +- "delegated requests finish, asp = %8p\n", asp)); ++ "delegated requests finish, asp = %8p\n", ++ agent_delegated_list)); + break; + } + #endif /* NETSNMP_NO_WRITE_SUPPORT */ +@@ -2880,6 +2904,11 @@ check_delayed_request(netsnmp_agent_sess + case SNMP_MSG_GETBULK: + case SNMP_MSG_GETNEXT: + netsnmp_check_all_requests_status(asp, 0); ++ if (agent_snmp_session_is_cancelled(asp)) { ++ printf("request %p is cancelled\n", asp); ++ DEBUGMSGTL(("snmp_agent","canceling next walk for asp %p\n", asp)); ++ break; ++ } + handle_getnext_loop(asp); + if (netsnmp_check_for_delegated(asp) && + netsnmp_check_transaction_id(asp->pdu->transid) != +@@ -3838,4 +3867,73 @@ netsnmp_set_all_requests_error(netsnmp_a + return error_value; + } + #endif /* NETSNMP_FEATURE_REMOVE_SET_ALL_REQUESTS_ERROR */ ++ ++/* ++ * Ugly hack to fix bug #950602 and preserve ABI ++ * (the official patch adds netsnmp_agent_session->flags). ++ * We must create parallel database of netsnmp_agent_sessions ++ * and put cancelled requests there instead of marking ++ * netsnmp_agent_session->flags. ++ */ ++static netsnmp_agent_session **cancelled_agent_snmp_sessions; ++static int cancelled_agent_snmp_sessions_count; ++static int cancelled_agent_snmp_sessions_max; ++ ++int ++agent_snmp_session_mark_cancelled(netsnmp_agent_session *session) ++{ ++ DEBUGMSGTL(("agent:cancelled", "Cancelling session %p\n", session)); ++ if (!session) ++ return 0; ++ if (cancelled_agent_snmp_sessions_count + 1 > cancelled_agent_snmp_sessions_max) { ++ netsnmp_agent_session **aux; ++ int max = cancelled_agent_snmp_sessions_max + 10; ++ aux = realloc(cancelled_agent_snmp_sessions, sizeof(netsnmp_agent_session*) * max); ++ if (!aux) ++ return SNMP_ERR_GENERR; ++ cancelled_agent_snmp_sessions = aux; ++ cancelled_agent_snmp_sessions_max = max; ++ } ++ cancelled_agent_snmp_sessions[cancelled_agent_snmp_sessions_count] = session; ++ cancelled_agent_snmp_sessions_count++; ++ return 0; ++} ++ ++int ++agent_snmp_session_is_cancelled(netsnmp_agent_session *session) ++{ ++ int i; ++ for (i=0; i +Date: Tue Feb 7 14:53:44 2012 +0100 + + CHANGES: PATCH 1633670: fixed snmpd crashing when an AgentX subagent disconnect in the middle of processing of a request. + + I fixed also the memory leak reported in the tracker comments. + +diff --git a/agent/mibgroup/agentx/master.c b/agent/mibgroup/agentx/master.c +index c42a42a..baeebaf 100644 +--- a/agent/mibgroup/agentx/master.c ++++ b/agent/mibgroup/agentx/master.c +@@ -219,6 +219,9 @@ agentx_got_response(int operation, + if (!cache) { + DEBUGMSGTL(("agentx/master", "response too late on session %8p\n", + session)); ++ /* response is too late, free the cache */ ++ if (magic) ++ netsnmp_free_delegated_cache((netsnmp_delegated_cache*) magic); + return 0; + } + requests = cache->requests; +@@ -606,6 +609,8 @@ agentx_master_handler(netsnmp_mib_handler *handler, + result = snmp_async_send(ax_session, pdu, agentx_got_response, cb_data); + if (result == 0) { + snmp_free_pdu(pdu); ++ if (cb_data) ++ netsnmp_free_delegated_cache((netsnmp_delegated_cache*) cb_data); + } + + return SNMP_ERR_NOERROR; +diff --git a/agent/mibgroup/agentx/master_admin.c b/agent/mibgroup/agentx/master_admin.c +index f16f392..b84b85e 100644 +--- a/agent/mibgroup/agentx/master_admin.c ++++ b/agent/mibgroup/agentx/master_admin.c +@@ -133,11 +133,16 @@ close_agentx_session(netsnmp_session * session, int sessid) + * requests, so that the delegated request will be completed and + * further requests can be processed + */ +- netsnmp_remove_delegated_requests_for_session(session); ++ while (netsnmp_remove_delegated_requests_for_session(session)) { ++ DEBUGMSGTL(("agentx/master", "Continue removing delegated reqests\n")); ++ } ++ + if (session->subsession != NULL) { + netsnmp_session *subsession = session->subsession; + for(; subsession; subsession = subsession->next) { +- netsnmp_remove_delegated_requests_for_session(subsession); ++ while (netsnmp_remove_delegated_requests_for_session(subsession)) { ++ DEBUGMSGTL(("agentx/master", "Continue removing delegated subsession reqests\n")); ++ } + } + } + diff --git a/net-snmp.spec b/net-snmp.spec index 6da14f7..36a3a9f 100644 --- a/net-snmp.spec +++ b/net-snmp.spec @@ -11,7 +11,7 @@ Summary: A collection of SNMP protocol tools and libraries Name: net-snmp Version: 5.7.2 -Release: 15%{?dist} +Release: 16%{?dist} Epoch: 1 License: BSD @@ -40,6 +40,8 @@ Patch7: net-snmp-5.7.2-python-ipaddress-size.patch Patch8: net-snmp-5.7.2-create-user-multilib.patch Patch9: net-snmp-5.7.2-autoreconf.patch Patch10: net-snmp-5.7.2-btrfs.patch +Patch11: net-snmp-5.7-agentx-crash.patch +Patch12: net-snmp-5.5-agentx-disconnect-crash.patch Requires(post): chkconfig Requires(preun): chkconfig @@ -204,6 +206,8 @@ cp %{SOURCE12} . %patch8 -p1 -b .multilib %patch9 -p1 -b .autoreconf %patch10 -p1 -b .btrfs +%patch11 -p1 -b .agentx-crash +%patch12 -p1 -b .agentx-disconnect-crash %ifarch sparc64 s390 s390x # disable failing test - see https://bugzilla.redhat.com/show_bug.cgi?id=680697 @@ -505,6 +509,10 @@ rm -rf ${RPM_BUILD_ROOT} %{_initrddir}/snmptrapd %changelog +* Thu Dec 5 2013 Jan Safranek - 1:5.7.2-16 +- Fixed snmpd crashing when AgentX subagent disconnects in the middle of + request processing (#1038011) + * Sat Aug 03 2013 Fedora Release Engineering - 1:5.7.2-15 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild @@ -514,7 +522,7 @@ rm -rf ${RPM_BUILD_ROOT} * Thu Jun 27 2013 Jan Safranek - 1:5.7.2-13 - set permissions of snmpd.conf and snmptrapd conf to 0600 to prevent users from reading passwords and community strings. - + * Tue May 21 2013 Jan Safranek - 1:5.7.2-12 - added btrfs support to hrFSTable (#965348)