18529953 CVE-2012-6151: DoS via AgentX subagent timeout in net-snmp s11u2-sru
authorTomas Klacko <tomas.klacko@oracle.com>
Mon, 22 Sep 2014 14:30:40 +0200
branchs11u2-sru
changeset 3315 30430ad22b5d
parent 3314 d9e2a20bc0aa
child 3316 4586c8c1a4b1
18529953 CVE-2012-6151: DoS via AgentX subagent timeout in net-snmp
components/net-snmp/patches/047.18529953.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/047.18529953.patch	Mon Sep 22 14:30:40 2014 +0200
@@ -0,0 +1,199 @@
+http://sourceforge.net/p/net-snmp/code/ci/793d596838ff7cb48a73b675d62897c56c9e62df
+http://sourceforge.net/p/net-snmp/patches/1237/?page=0
+
+diff --git a/agent/mibgroup/agentx/master_admin.c b/agent/mibgroup/agentx/master_admin.c
+index a04b18a..82c1fbf 100644
+--- a/agent/mibgroup/agentx/master_admin.c
++++ b/agent/mibgroup/agentx/master_admin.c
[email protected]@ -161,6 +161,7 @@ close_agentx_session(netsnmp_session * session, int sessid)
+     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);
+             snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
+diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c
+index c655900..466ec4c 100644
+--- a/agent/snmp_agent.c
++++ b/agent/snmp_agent.c
[email protected]@ -1286,6 +1286,7 @@ init_agent_snmp_session(netsnmp_session * session, netsnmp_pdu *pdu)
+     asp->treecache_num = -1;
+     asp->treecache_len = 0;
+     asp->reqinfo = SNMP_MALLOC_TYPEDEF(netsnmp_agent_request_info);
++    asp->flags = SNMP_AGENT_FLAGS_NONE;
+     DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p created\n",
+                 asp, asp->reqinfo));
+ 
[email protected]@ -1338,6 +1339,9 @@ netsnmp_check_for_delegated(netsnmp_agent_session *asp)
+ 
+     if (NULL == asp->treecache)
+         return 0;
++
++    if (asp->flags & SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS)
++        return 0;
+     
+     for (i = 0; i <= asp->treecache_num; i++) {
+         for (request = asp->treecache[i].requests_begin; request;
[email protected]@ -1416,39 +1420,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) {
++            asp->flags |= SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS;
++            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 "
+-                    "%08p\n", count, sess));
+-        netsnmp_check_outstanding_agent_requests();
++                    "%08p\n", total_count, sess));
++        netsnmp_check_delegated_requests();
+     }
+     
+-    return count;
++    return total_count;
+ }
+ 
+ int
[email protected]@ -2587,19 +2600,11 @@ handle_var_requests(netsnmp_agent_session *asp)
+     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)) {
[email protected]@ -2638,6 +2643,22 @@ netsnmp_check_outstanding_agent_requests(void)
+             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
[email protected]@ -2666,7 +2687,8 @@ netsnmp_check_outstanding_agent_requests(void)
+ 
+             netsnmp_processing_set = netsnmp_agent_queued_list;
+             DEBUGMSGTL(("snmp_agent", "SET request remains queued while "
+-                        "delegated requests finish, asp = %08p\n", asp));
++                        "delegated requests finish, asp = %08p\n",
++                        agent_delegated_list));
+             break;
+         }
+ 
[email protected]@ -2726,6 +2748,10 @@ check_delayed_request(netsnmp_agent_session *asp)
+     case SNMP_MSG_GETBULK:
+     case SNMP_MSG_GETNEXT:
+         netsnmp_check_all_requests_status(asp, 0);
++        if (asp->flags & SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS) {
++            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) !=
+diff --git a/include/net-snmp/agent/snmp_agent.h b/include/net-snmp/agent/snmp_agent.h
+index fd84f0f..efbeb5b 100644
+--- a/include/net-snmp/agent/snmp_agent.h
++++ b/include/net-snmp/agent/snmp_agent.h
[email protected]@ -32,6 +32,9 @@ extern          "C" {
+ #define SNMP_MAX_PDU_SIZE 64000 /* local constraint on PDU size sent by agent
+                                  * (see also SNMP_MAX_MSG_SIZE in snmp_api.h) */
+ 
++#define SNMP_AGENT_FLAGS_NONE                   0x0
++#define SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS     0x1
++
+     /*
+      * If non-zero, causes the addresses of peers to be logged when receptions
+      * occur.  
[email protected]@ -197,6 +200,7 @@ extern          "C" {
+         int             treecache_num;  /* number of current cache entries */
+         netsnmp_cachemap *cache_store;
+         int             vbcount;
++        int             flags;
+     } netsnmp_agent_session;
+ 
+     /*
[email protected]@ -231,6 +235,7 @@ extern          "C" {
+     int             init_master_agent(void);
+     void            shutdown_master_agent(void);
+     int             agent_check_and_process(int block);
++    void            netsnmp_check_delegated_requests(void);
+     void            netsnmp_check_outstanding_agent_requests(void);
+ 
+     int             netsnmp_request_set_error(netsnmp_request_info *request,
+