1
Description: fix denial of service via AgentX subagent timeout
2
Origin: based on RedHat's backport of upstream commits. Thanks!
3
Origin: backport, http://sourceforge.net/p/net-snmp/code/ci/f9304c83f76202db0e684269ca1af32e43cd9db4
4
Origin: backport, http://sourceforge.net/p/net-snmp/code/ci/793d596838ff7cb48a73b675d62897c56c9e62df
5
Bug: http://sourceforge.net/p/net-snmp/bugs/2411/
6
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=731625
7
Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-6151
9
Index: net-snmp-5.7.2~dfsg/agent/mibgroup/agentx/master.c
10
===================================================================
11
--- net-snmp-5.7.2~dfsg.orig/agent/mibgroup/agentx/master.c 2012-10-09 18:28:58.000000000 -0400
12
+++ net-snmp-5.7.2~dfsg/agent/mibgroup/agentx/master.c 2014-03-11 09:16:01.212180291 -0400
15
DEBUGMSGTL(("agentx/master", "response too late on session %8p\n",
18
+ /* response is too late, free the cache */
20
+ netsnmp_free_delegated_cache((netsnmp_delegated_cache*) magic);
23
requests = cache->requests;
26
result = snmp_async_send(ax_session, pdu, agentx_got_response, cb_data);
30
+ netsnmp_free_delegated_cache((netsnmp_delegated_cache*) cb_data);
33
return SNMP_ERR_NOERROR;
34
Index: net-snmp-5.7.2~dfsg/agent/mibgroup/agentx/master_admin.c
35
===================================================================
36
--- net-snmp-5.7.2~dfsg.orig/agent/mibgroup/agentx/master_admin.c 2012-10-09 18:28:58.000000000 -0400
37
+++ net-snmp-5.7.2~dfsg/agent/mibgroup/agentx/master_admin.c 2014-03-11 09:15:22.624179258 -0400
39
* requests, so that the delegated request will be completed and
40
* further requests can be processed
42
- netsnmp_remove_delegated_requests_for_session(session);
43
+ while (netsnmp_remove_delegated_requests_for_session(session)) {
44
+ DEBUGMSGTL(("agentx/master", "Continue removing delegated reqests\n"));
47
if (session->subsession != NULL) {
48
netsnmp_session *subsession = session->subsession;
49
for(; subsession; subsession = subsession->next) {
50
- netsnmp_remove_delegated_requests_for_session(subsession);
51
+ while (netsnmp_remove_delegated_requests_for_session(subsession)) {
52
+ DEBUGMSGTL(("agentx/master", "Continue removing delegated subsession reqests\n"));
58
for (sp = session->subsession; sp != NULL; sp = sp->next) {
60
if (sp->sessid == sessid) {
61
+ netsnmp_remove_delegated_requests_for_session(sp);
62
unregister_mibs_by_session(sp);
63
unregister_index_by_session(sp);
64
unregister_sysORTable_by_session(sp);
65
Index: net-snmp-5.7.2~dfsg/agent/snmp_agent.c
66
===================================================================
67
--- net-snmp-5.7.2~dfsg.orig/agent/snmp_agent.c 2012-10-09 18:28:58.000000000 -0400
68
+++ net-snmp-5.7.2~dfsg/agent/snmp_agent.c 2014-03-11 09:17:09.304182115 -0400
70
netsnmp_free_cachemap(asp->cache_store);
71
asp->cache_store = NULL;
73
+ agent_snmp_session_release_cancelled(asp);
77
@@ -1457,6 +1458,10 @@
79
if (NULL == asp->treecache)
82
+ if (agent_snmp_session_is_cancelled(asp)) {
86
for (i = 0; i <= asp->treecache_num; i++) {
87
for (request = asp->treecache[i].requests_begin; request;
88
@@ -1535,39 +1540,48 @@
89
netsnmp_remove_delegated_requests_for_session(netsnmp_session *sess)
91
netsnmp_agent_session *asp;
93
+ int total_count = 0;
95
for (asp = agent_delegated_list; asp; asp = asp->next) {
101
netsnmp_request_info *request;
102
- for(request = asp->requests; request; request = request->next) {
106
- netsnmp_assert(NULL!=request->subtree);
107
- if(request->subtree->session != sess)
109
+ for (i = 0; i <= asp->treecache_num; i++) {
110
+ for (request = asp->treecache[i].requests_begin; request;
111
+ request = request->next) {
115
+ netsnmp_assert(NULL!=request->subtree);
116
+ if(request->subtree->session != sess)
120
- * matched! mark request as done
122
- netsnmp_request_set_error(request, SNMP_ERR_GENERR);
125
+ * matched! mark request as done
127
+ netsnmp_request_set_error(request, SNMP_ERR_GENERR);
132
+ agent_snmp_session_mark_cancelled(asp);
133
+ total_count += count;
138
* if we found any, that request may be finished now
142
DEBUGMSGTL(("snmp_agent", "removed %d delegated request(s) for session "
143
- "%8p\n", count, sess));
144
- netsnmp_check_outstanding_agent_requests();
145
+ "%8p\n", total_count, sess));
146
+ netsnmp_check_delegated_requests();
150
+ return total_count;
154
@@ -2739,19 +2753,11 @@
159
- * loop through our sessions known delegated sessions and check to see
160
- * if they've completed yet. If there are no more delegated sessions,
161
- * check for and process any queued requests
164
-netsnmp_check_outstanding_agent_requests(void)
165
+netsnmp_check_delegated_requests(void)
167
netsnmp_agent_session *asp, *prev_asp = NULL, *next_asp = NULL;
170
- * deal with delegated requests
172
for (asp = agent_delegated_list; asp; asp = next_asp) {
173
next_asp = asp->next; /* save in case we clean up asp */
174
if (!netsnmp_check_for_delegated(asp)) {
175
@@ -2790,6 +2796,22 @@
182
+ * loop through our sessions known delegated sessions and check to see
183
+ * if they've completed yet. If there are no more delegated sessions,
184
+ * check for and process any queued requests
187
+netsnmp_check_outstanding_agent_requests(void)
189
+ netsnmp_agent_session *asp;
192
+ * deal with delegated requests
194
+ netsnmp_check_delegated_requests();
197
* if we are processing a set and there are more delegated
198
@@ -2819,7 +2841,8 @@
200
netsnmp_processing_set = netsnmp_agent_queued_list;
201
DEBUGMSGTL(("snmp_agent", "SET request remains queued while "
202
- "delegated requests finish, asp = %8p\n", asp));
203
+ "delegated requests finish, asp = %8p\n",
204
+ agent_delegated_list));
207
#endif /* NETSNMP_NO_WRITE_SUPPORT */
208
@@ -2880,6 +2903,10 @@
209
case SNMP_MSG_GETBULK:
210
case SNMP_MSG_GETNEXT:
211
netsnmp_check_all_requests_status(asp, 0);
212
+ if (agent_snmp_session_is_cancelled(asp)) {
213
+ DEBUGMSGTL(("snmp_agent","canceling next walk for asp %p\n", asp));
216
handle_getnext_loop(asp);
217
if (netsnmp_check_for_delegated(asp) &&
218
netsnmp_check_transaction_id(asp->pdu->transid) !=
219
@@ -3836,3 +3863,71 @@
221
#endif /* NETSNMP_FEATURE_REMOVE_SET_ALL_REQUESTS_ERROR */
226
+ * Ugly hack to fix bug #950602 and preserve ABI
227
+ * (the official patch adds netsnmp_agent_session->flags).
228
+ * We must create parallel database of netsnmp_agent_sessions
229
+ * and put cancelled requests there instead of marking
230
+ * netsnmp_agent_session->flags.
232
+static netsnmp_agent_session **cancelled_agent_snmp_sessions;
233
+static int cancelled_agent_snmp_sessions_count;
234
+static int cancelled_agent_snmp_sessions_max;
237
+agent_snmp_session_mark_cancelled(netsnmp_agent_session *session)
239
+ DEBUGMSGTL(("agent:cancelled", "Cancelling session %p\n", session));
242
+ if (cancelled_agent_snmp_sessions_count + 1 > cancelled_agent_snmp_sessions_max) {
243
+ netsnmp_agent_session **aux;
244
+ int max = cancelled_agent_snmp_sessions_max + 10;
245
+ aux = realloc(cancelled_agent_snmp_sessions, sizeof(netsnmp_agent_session*) * max);
247
+ return SNMP_ERR_GENERR;
248
+ cancelled_agent_snmp_sessions = aux;
249
+ cancelled_agent_snmp_sessions_max = max;
251
+ cancelled_agent_snmp_sessions[cancelled_agent_snmp_sessions_count] = session;
252
+ cancelled_agent_snmp_sessions_count++;
257
+agent_snmp_session_is_cancelled(netsnmp_agent_session *session)
260
+ for (i=0; i<cancelled_agent_snmp_sessions_count; i++)
261
+ if (cancelled_agent_snmp_sessions[i] == session) {
262
+ DEBUGMSGTL(("agent:cancelled", "session %p is cancelled\n", session));
269
+agent_snmp_session_release_cancelled(netsnmp_agent_session *session)
276
+ DEBUGMSGTL(("agent:cancelled", "Removing session %p\n", session));
278
+ /* delete the session from cancelled_agent_snmp_sessions */
279
+ for (i=0, j=0; j<cancelled_agent_snmp_sessions_count; i++, j++)
280
+ if (cancelled_agent_snmp_sessions[j] == session)
281
+ i--; /* don't increase i in this loop iteration */
283
+ cancelled_agent_snmp_sessions[i] = cancelled_agent_snmp_sessions[j];
285
+ cancelled_agent_snmp_sessions_count = i;
287
+ for (; i< cancelled_agent_snmp_sessions_max; i++)
288
+ cancelled_agent_snmp_sessions[i] = NULL;
291
Index: net-snmp-5.7.2~dfsg/include/net-snmp/agent/snmp_agent.h
292
===================================================================
293
--- net-snmp-5.7.2~dfsg.orig/include/net-snmp/agent/snmp_agent.h 2012-10-09 18:28:58.000000000 -0400
294
+++ net-snmp-5.7.2~dfsg/include/net-snmp/agent/snmp_agent.h 2014-03-11 09:15:22.628179258 -0400
296
int init_master_agent(void);
297
void shutdown_master_agent(void);
298
int agent_check_and_process(int block);
299
+ void netsnmp_check_delegated_requests(void);
300
void netsnmp_check_outstanding_agent_requests(void);
302
int netsnmp_request_set_error(netsnmp_request_info *request,