I remade a patch for latest FedoraCore user(net-snmp-5.2.1-9.rpm)
Thanks!
-nagata

Tsuyoshi Nagata wrote:

>This is the 2nd patch for fixing snmp_free_session(session) problem.
>
>double free was born by follows.
>snmp_free_session() frees session.
>clear_callbacks() frees session.
>
>And, I send SPEC file for RHEL4 user.
>
>PLEASE discard my dirty
>[net-snmp-5.1.2-agentx_register_callbacks_entry.patch] .
>It fix this clear_callback problem, but this 2 patch helps much better.
>
>NG:net-snmp-5.1.2-agentx_register_callbacks_entry.patch <- My previous work.
>OK:net-snmp-5.1.2-clear_callback3.patch <- Robert's _remove_duplicates
>patch for 5.1.2
>OK:net-snmp-5.1.2-free_session.patch <- fix snmp_free_session() free
>problem.
>
>
>
>Thanks .
>-Nagata
>
>  
>
diff -Naurp net-snmp-5.2.1/snmplib/callback.c 
net-snmp-5.2.1.n/snmplib/callback.c
--- net-snmp-5.2.1/snmplib/callback.c   2004-09-22 06:59:41.000000000 +0900
+++ net-snmp-5.2.1.n/snmplib/callback.c 2005-04-18 11:54:29.264199931 +0900
@@ -45,6 +45,10 @@
 #include <net-snmp/library/callback.h>
 #include <net-snmp/library/snmp_api.h>
 
+
+static void _remove_duplicates(void *ptr, int x, int y);
+
+
 static struct snmp_gen_callback
                *thecallbacks[MAX_CALLBACK_IDS][MAX_CALLBACK_SUBIDS];
 
@@ -335,11 +339,34 @@ snmp_unregister_callback(int major, int 
     return count;
 }
 
+static void
+_remove_duplicates(void *ptr, int x, int y)
+{
+    struct snmp_gen_callback *scp = NULL, *next = NULL;
+    int i,j;
+    for (i=x; i < MAX_CALLBACK_IDS; i++) {
+       for (j=y; j < MAX_CALLBACK_SUBIDS; j++) {
+           scp = thecallbacks[i][j]; 
+           while (scp != NULL) {
+                next=scp->next;
+               if ((NULL != scp->sc_callback) &&
+                     (scp->sc_client_arg != NULL) &&
+                     (scp->sc_client_arg == ptr)) {
+                   DEBUGMSGTL(("callback", "duplicate client arg\n"));
+                   scp->sc_client_arg = NULL;
+               }
+               scp = next;
+           }
+       }
+    }
+}
+
 void
 clear_callback(void)
 {
     unsigned int i = 0, j = 0; 
     struct snmp_gen_callback *scp = NULL, *next = NULL;
+    void *tmp_arg;
 
     if(++_lock > 1) {
         snmp_log(LOG_WARNING,
@@ -352,8 +379,23 @@ clear_callback(void)
            scp = thecallbacks[i][j]; 
            while (scp != NULL) {
                next = scp->next;
+                 /*
+                  * if there is a client arg, check for duplicates
+                  * and then free it.
+                  */
                if ((NULL != scp->sc_callback) && (scp->sc_client_arg != NULL))
-                   SNMP_FREE(scp->sc_client_arg);
+                     (scp->sc_client_arg != NULL)) {
+                    /*
+                     * save the client arg, then set it to null so that it
+                     * won't look like a duplicate, then check for duplicates
+                     * starting at the current i,j (earlier dups should have
+                     * already been found) and free the pointer.
+                     */
+                     tmp_arg = scp->sc_client_arg;
+                    scp->sc_client_arg = NULL;
+                     _remove_duplicates(tmp_arg, i, j);
+                     free(tmp_arg);
+                }
                SNMP_FREE(scp);
                scp = next;
            }
diff -Naurp net-snmp-5.2.1/include/net-snmp/library/callback.h 
net-snmp-5.2.1.n/include/net-snmp/library/callback.h
--- net-snmp-5.2.1/include/net-snmp/library/callback.h  2003-07-14 
03:19:23.000000000 +0900
+++ net-snmp-5.2.1.n/include/net-snmp/library/callback.h        2005-04-18 
11:57:45.778254111 +0900
@@ -57,6 +57,7 @@ extern          "C" {
                                              SNMPCallback * new_callback,
                                              void *arg, int matchargs);
     void            clear_callback (void);
+    void            clear_callback_session (void *session);
     struct snmp_gen_callback *snmp_callback_list(int major, int minor);
 
 #ifdef __cplusplus
diff -Naurp net-snmp-5.2.1/snmplib/callback.c 
net-snmp-5.2.1.n/snmplib/callback.c
--- net-snmp-5.2.1/snmplib/callback.c   2005-04-18 11:58:50.121568379 +0900
+++ net-snmp-5.2.1.n/snmplib/callback.c 2005-04-18 11:57:45.779230326 +0900
@@ -405,6 +405,14 @@ clear_callback(void)
     --_lock;
 }
 
+void
+clear_callback_session(void*session)
+{
+
+    _remove_duplicates(session, 0, 0);
+
+}
+
 struct snmp_gen_callback *
 snmp_callback_list(int major, int minor)
 {
diff -Naurp net-snmp-5.2.1/snmplib/snmp_api.c 
net-snmp-5.2.1.n/snmplib/snmp_api.c
--- net-snmp-5.2.1/snmplib/snmp_api.c   2005-04-18 11:58:27.494854499 +0900
+++ net-snmp-5.2.1.n/snmplib/snmp_api.c 2005-04-18 11:57:45.785087617 +0900
@@ -1784,6 +1784,8 @@ snmp_free_session(netsnmp_session * s)
         SNMP_FREE(s->securityName);
         SNMP_FREE(s->securityAuthProto);
         SNMP_FREE(s->securityPrivProto);
+        /* session information already frees in snmp_shutdown. */
+        clear_callback_session(s);
         free((char *) s);
     }
 }

Reply via email to