Browse Source

Bug(s) fixed: 179135
Bug Description: memory leaks using ber_scanf when handling bad BER packets
Reviewed by: All (Thanks!)
Files: https://bugzilla.redhat.com/bugzilla/attachment.cgi?id=123783
Branch: HEAD
Fix Description:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=179135#c0
I basically did a search through our code for all calls to ber_scanf,
ber_get_stringa, and ber_get_stringal and made sure we properly free any
arguments that may have been allocated. There was a bug in the ldapsdk
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=179135 that causes
us to free uninitialized memory when trying to clean up the result of
ber_get_stringal (or ber_scanf with 'V'). I had to initialize some
variables to NULL so that we could properly clean them up, and added
some additional clean ups that were missing. Also, in repl_extop.c, we
were calling free on an array that we should have been calling
ch_array_free on. Yet another lesson in the evils of slapi_ch_free and
disabling compiler type checks in general.
Platforms tested: Fedora Core 4
Flag Day: no
Doc impact: no

Rich Megginson 20 years ago
parent
commit
d62cdb091a

+ 4 - 1
ldap/servers/plugins/replication/repl5_total.c

@@ -585,7 +585,7 @@ my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
     char *lasti;
     char *lasti;
     unsigned long len;
     unsigned long len;
 	unsigned long tag;
 	unsigned long tag;
-    char *str;
+    char *str = NULL;
     int rc;
     int rc;
     Slapi_Value *value;
     Slapi_Value *value;
 
 
@@ -685,6 +685,9 @@ loser:
     if (value)
     if (value)
         slapi_value_free (&value);
         slapi_value_free (&value);
 
 
+    slapi_ch_free_string(&attrtype);
+    slapi_ch_free_string(&str);
+
     return -1;    
     return -1;    
 }
 }
 
 

+ 4 - 4
ldap/servers/plugins/replication/repl_controls.c

@@ -349,15 +349,15 @@ add_repl_control_mods( Slapi_PBlock *pb, Slapi_Mods *smods )
         		      emtag != LBER_ERROR && emtag != LBER_END_OF_SEQORSET;
         		      emtag != LBER_ERROR && emtag != LBER_END_OF_SEQORSET;
         		      emtag = ber_next_element( ember, &emlen, emlast ))
         		      emtag = ber_next_element( ember, &emlen, emlast ))
 			    {
 			    {
-        		    struct berval **embvals;
-        		    if ( ber_scanf( ember, "{i{a[V]}}", &op, &type, &embvals ) == LBER_ERROR )
+        		    struct berval **embvals = NULL;
+        		    type = NULL;
+        		    if ( ber_scanf( ember, "{i{a[V]}}", &op, &type, &embvals ) != LBER_ERROR )
 					{
 					{
-            			continue;
+        				slapi_mods_add_modbvps( smods, op, type, embvals);
 					/* GGOODREPL I suspect this will cause two sets of lastmods attr values
 					/* GGOODREPL I suspect this will cause two sets of lastmods attr values
 						to end up in the entry. We need to remove the old ones.
 						to end up in the entry. We need to remove the old ones.
 					*/
 					*/
         		    }
         		    }
-                    slapi_mods_add_modbvps( smods, op, type, embvals);
         		    free( type );
         		    free( type );
         		    ber_bvecfree( embvals );
         		    ber_bvecfree( embvals );
         		}
         		}

+ 2 - 1
ldap/servers/plugins/replication/repl_extop.c

@@ -384,7 +384,8 @@ free_and_return:
 		/* slapi_ch_free accepts NULL pointer */
 		/* slapi_ch_free accepts NULL pointer */
 		slapi_ch_free ((void**)protocol_oid);
 		slapi_ch_free ((void**)protocol_oid);
 		slapi_ch_free ((void**)repl_root);
 		slapi_ch_free ((void**)repl_root);
-		slapi_ch_free ((void **)extra_referrals);
+		slapi_ch_array_free (*extra_referrals);
+        *extra_referrals = NULL;
 		slapi_ch_free ((void**)csnstr);
 		slapi_ch_free ((void**)csnstr);
 
 
 		if (*supplier_ruv)
 		if (*supplier_ruv)

+ 7 - 4
ldap/servers/slapd/add.c

@@ -102,8 +102,9 @@ do_add( Slapi_PBlock *pb )
 	 */
 	 */
 	/* get the name */
 	/* get the name */
 	{
 	{
-    	char *dn;
+    	char *dn = NULL;
     	if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
     	if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
+            slapi_ch_free_string(&dn);
     		LDAPDebug( LDAP_DEBUG_ANY,
     		LDAPDebug( LDAP_DEBUG_ANY,
     		    "ber_scanf failed (op=Add; params=DN)\n", 0, 0, 0 );
     		    "ber_scanf failed (op=Add; params=DN)\n", 0, 0, 0 );
 			op_shared_log_error_access (pb, "ADD", "???", "decoding error");
 			op_shared_log_error_access (pb, "ADD", "???", "decoding error");
@@ -121,11 +122,13 @@ do_add( Slapi_PBlock *pb )
 	      tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET;
 	      tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET;
 	      tag = ber_next_element( ber, &len, last ) ) {
 	      tag = ber_next_element( ber, &len, last ) ) {
 		char *type = NULL, *normtype = NULL;
 		char *type = NULL, *normtype = NULL;
-		struct berval	**vals;
+		struct berval	**vals = NULL;
 		if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
 		if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error");
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error");
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			    "decoding error", 0, NULL );
 			    "decoding error", 0, NULL );
+            slapi_ch_free_string(&type);
+            ber_bvecfree( vals );
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 
 
@@ -134,7 +137,7 @@ do_add( Slapi_PBlock *pb )
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "null value");
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "null value");
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL,
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL,
 			    0, NULL );
 			    0, NULL );
-			free( type );			
+            slapi_ch_free_string(&type);
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 
 
@@ -144,7 +147,7 @@ do_add( Slapi_PBlock *pb )
 			PR_snprintf (ebuf, BUFSIZ, "invalid type '%s'", type);
 			PR_snprintf (ebuf, BUFSIZ, "invalid type '%s'", type);
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), ebuf);
 			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), ebuf);
 			send_ldap_result( pb, rc, NULL, ebuf, 0, NULL );
 			send_ldap_result( pb, rc, NULL, ebuf, 0, NULL );
-			free( type );
+            slapi_ch_free_string(&type);
 			slapi_ch_free( (void**)&normtype );
 			slapi_ch_free( (void**)&normtype );
 			ber_bvecfree( vals );
 			ber_bvecfree( vals );
 			goto free_and_return;
 			goto free_and_return;

+ 3 - 1
ldap/servers/slapd/ava.c

@@ -53,10 +53,12 @@ get_ava(
     struct ava	*ava
     struct ava	*ava
 )
 )
 {
 {
-	char	*type;
+	char	*type = NULL;
 
 
 	if ( ber_scanf( ber, "{ao}", &type, &ava->ava_value )
 	if ( ber_scanf( ber, "{ao}", &type, &ava->ava_value )
 	    == LBER_ERROR ) {
 	    == LBER_ERROR ) {
+        slapi_ch_free_string(&type);
+        ava_done(ava);
 		LDAPDebug( LDAP_DEBUG_ANY, "  get_ava ber_scanf\n", 0, 0, 0 );
 		LDAPDebug( LDAP_DEBUG_ANY, "  get_ava ber_scanf\n", 0, 0, 0 );
 		return( LDAP_PROTOCOL_ERROR );
 		return( LDAP_PROTOCOL_ERROR );
 	}
 	}

+ 1 - 0
ldap/servers/slapd/back-ldbm/sort.c

@@ -384,6 +384,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps)
 
 
 		return_value = ber_scanf(ber,"a",&rtype);
 		return_value = ber_scanf(ber,"a",&rtype);
 		if (LBER_ERROR == return_value) {
 		if (LBER_ERROR == return_value) {
+			slapi_ch_free_string(&rtype);
 			rc = LDAP_PROTOCOL_ERROR;
 			rc = LDAP_PROTOCOL_ERROR;
                         goto err;
                         goto err;
 		}
 		}

+ 2 - 1
ldap/servers/slapd/bind.c

@@ -111,7 +111,7 @@ do_bind( Slapi_PBlock *pb )
     long ber_version = -1;
     long ber_version = -1;
     int		auth_response_requested = 0;
     int		auth_response_requested = 0;
     int		pw_response_requested = 0;
     int		pw_response_requested = 0;
-    char		*dn, *saslmech = NULL;
+    char		*dn = NULL, *saslmech = NULL;
     struct berval	cred = {0};
     struct berval	cred = {0};
     Slapi_Backend		*be = NULL;
     Slapi_Backend		*be = NULL;
     unsigned long rc;
     unsigned long rc;
@@ -154,6 +154,7 @@ do_bind( Slapi_PBlock *pb )
         log_bind_access (pb, "???", method, version, saslmech, "decoding error");
         log_bind_access (pb, "???", method, version, saslmech, "decoding error");
         send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
         send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
                           "decoding error", 0, NULL );
                           "decoding error", 0, NULL );
+        slapi_ch_free_string(&dn);
         return;
         return;
     }
     }
 
 

+ 9 - 5
ldap/servers/slapd/compare.c

@@ -60,13 +60,13 @@ void
 do_compare( Slapi_PBlock *pb )
 do_compare( Slapi_PBlock *pb )
 {
 {
 	BerElement	*ber = pb->pb_op->o_ber;
 	BerElement	*ber = pb->pb_op->o_ber;
-	char		*dn;
-	struct ava	ava;
+	char		*dn = NULL;
+	struct ava	ava = {0};
 	Slapi_Backend		*be = NULL;
 	Slapi_Backend		*be = NULL;
 	int		err;
 	int		err;
 	char		ebuf[ BUFSIZ ];
 	char		ebuf[ BUFSIZ ];
 	Slapi_DN sdn;
 	Slapi_DN sdn;
-	Slapi_Entry *referral;
+	Slapi_Entry *referral = NULL;
 	char errorbuf[BUFSIZ];
 	char errorbuf[BUFSIZ];
 
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
@@ -74,6 +74,9 @@ do_compare( Slapi_PBlock *pb )
 	/* count the compare request */
 	/* count the compare request */
 	PR_AtomicIncrement(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
 	PR_AtomicIncrement(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
 
 
+    /* have to init this here so we can "done" it below if we short circuit */
+    slapi_sdn_init(&sdn);
+
 	/*
 	/*
 	 * Parse the compare request.  It looks like this:
 	 * Parse the compare request.  It looks like this:
 	 *
 	 *
@@ -86,7 +89,6 @@ do_compare( Slapi_PBlock *pb )
 	 *	}
 	 *	}
 	 */
 	 */
 
 
-
 	if ( ber_scanf( ber, "{a{ao}}", &dn, &ava.ava_type,
 	if ( ber_scanf( ber, "{a{ao}}", &dn, &ava.ava_type,
 	    &ava.ava_value ) == LBER_ERROR ) {
 	    &ava.ava_value ) == LBER_ERROR ) {
 		LDAPDebug( LDAP_DEBUG_ANY,
 		LDAPDebug( LDAP_DEBUG_ANY,
@@ -94,7 +96,7 @@ do_compare( Slapi_PBlock *pb )
 		    0, 0, 0 );
 		    0, 0, 0 );
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
 		    NULL );
 		    NULL );
-		return;
+		goto free_and_return;
 	}
 	}
 	/*
 	/*
 	 * in LDAPv3 there can be optional control extensions on
 	 * in LDAPv3 there can be optional control extensions on
@@ -106,6 +108,7 @@ do_compare( Slapi_PBlock *pb )
 		goto free_and_return;
 		goto free_and_return;
 	}
 	}
 	slapi_sdn_init_dn_passin(&sdn,dn);
 	slapi_sdn_init_dn_passin(&sdn,dn);
+    dn = NULL; /* do not free - sdn owns it now */
 
 
 	/* target spec is used to decide which plugins are applicable for the operation */
 	/* target spec is used to decide which plugins are applicable for the operation */
 	operation_set_target_spec (pb->pb_op, &sdn);
 	operation_set_target_spec (pb->pb_op, &sdn);
@@ -181,5 +184,6 @@ free_and_return:;
 	if (be)
 	if (be)
 		slapi_be_Unlock(be);
 		slapi_be_Unlock(be);
 	slapi_sdn_done(&sdn);
 	slapi_sdn_done(&sdn);
+    slapi_ch_free_string(&dn);
 	ava_done( &ava );
 	ava_done( &ava );
 }
 }

+ 2 - 2
ldap/servers/slapd/delete.c

@@ -66,7 +66,7 @@ do_delete( Slapi_PBlock *pb )
 {
 {
 	Slapi_Operation *operation;
 	Slapi_Operation *operation;
 	BerElement	*ber;
 	BerElement	*ber;
-	char	    *dn;
+	char	    *dn = NULL;
 	int			err;
 	int			err;
 
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
@@ -89,7 +89,7 @@ do_delete( Slapi_PBlock *pb )
 		op_shared_log_error_access (pb, "DEL", "???", "decoding error");
 		op_shared_log_error_access (pb, "DEL", "???", "decoding error");
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
 		    NULL );
 		    NULL );
-		return;
+		goto free_and_return;
 	}
 	}
 
 
 	/*
 	/*

+ 8 - 3
ldap/servers/slapd/filter.c

@@ -175,7 +175,7 @@ get_filter_internal( Connection *conn, BerElement *ber,
     unsigned long	len;
     unsigned long	len;
     int		err;
     int		err;
     struct slapi_filter	*f;
     struct slapi_filter	*f;
-    char		*ftmp, *type;
+    char		*ftmp, *type = NULL;
 
 
 	LDAPDebug( LDAP_DEBUG_FILTER, "=> get_filter_internal\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_FILTER, "=> get_filter_internal\n", 0, 0, 0 );
 
 
@@ -293,6 +293,7 @@ get_filter_internal( Connection *conn, BerElement *ber,
 	case LDAP_FILTER_PRESENT:
 	case LDAP_FILTER_PRESENT:
 		LDAPDebug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
 		LDAPDebug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
 		if ( ber_scanf( ber, "a", &type ) == LBER_ERROR ) {
 		if ( ber_scanf( ber, "a", &type ) == LBER_ERROR ) {
+            slapi_ch_free_string(&type);
 			err = LDAP_PROTOCOL_ERROR;
 			err = LDAP_PROTOCOL_ERROR;
 		} else {
 		} else {
 			err = LDAP_SUCCESS;
 			err = LDAP_SUCCESS;
@@ -440,12 +441,13 @@ get_substring_filter(
 )
 )
 {
 {
 	unsigned long	tag, len, rc;
 	unsigned long	tag, len, rc;
-	char		*val, *last, *type;
+	char		*val, *last, *type = NULL;
 	char		ebuf[BUFSIZ];
 	char		ebuf[BUFSIZ];
 
 
 	LDAPDebug( LDAP_DEBUG_FILTER, "=> get_substring_filter\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_FILTER, "=> get_substring_filter\n", 0, 0, 0 );
 
 
 	if ( ber_scanf( ber, "{a", &type ) == LBER_ERROR ) {
 	if ( ber_scanf( ber, "{a", &type ) == LBER_ERROR ) {
+        slapi_ch_free_string(&type);
 		return( LDAP_PROTOCOL_ERROR );
 		return( LDAP_PROTOCOL_ERROR );
 	}
 	}
 	f->f_sub_type = slapi_attr_syntax_normalize( type );
 	f->f_sub_type = slapi_attr_syntax_normalize( type );
@@ -460,8 +462,10 @@ get_substring_filter(
 	    tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
 	    tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
 	    tag = ber_next_element( ber, &len, last ) )
 	    tag = ber_next_element( ber, &len, last ) )
 	{
 	{
+        val = NULL;
 		rc = ber_scanf( ber, "a", &val );
 		rc = ber_scanf( ber, "a", &val );
 		if ( rc == LBER_ERROR ) {
 		if ( rc == LBER_ERROR ) {
+            slapi_ch_free_string(&val);
 			return( LDAP_PROTOCOL_ERROR );
 			return( LDAP_PROTOCOL_ERROR );
 		}
 		}
 		if ( val == NULL || *val == '\0' ) {
 		if ( val == NULL || *val == '\0' ) {
@@ -573,8 +577,9 @@ get_extensible_filter( BerElement *ber, mr_filter_t* mrf )
 				}
 				}
 			}
 			}
 			{
 			{
-			    char* type;
+			    char* type = NULL;
 			    if (ber_scanf( ber, "a", &type ) == LBER_ERROR) {
 			    if (ber_scanf( ber, "a", &type ) == LBER_ERROR) {
+				slapi_ch_free_string (&type);
 				rc = LDAP_PROTOCOL_ERROR;
 				rc = LDAP_PROTOCOL_ERROR;
 			    } else {
 			    } else {
 				mrf->mrf_type = slapi_attr_syntax_normalize(type);
 				mrf->mrf_type = slapi_attr_syntax_normalize(type);

+ 5 - 2
ldap/servers/slapd/modify.c

@@ -114,7 +114,7 @@ do_modify( Slapi_PBlock *pb )
 {
 {
 	Slapi_Operation *operation;
 	Slapi_Operation *operation;
 	BerElement			*ber;
 	BerElement			*ber;
-	char				*last, *type;
+	char				*last, *type = NULL;
 	unsigned long		tag, len;
 	unsigned long		tag, len;
 	LDAPMod				*mod;
 	LDAPMod				*mod;
 	LDAPMod			    **mods;
 	LDAPMod			    **mods;
@@ -124,7 +124,7 @@ do_modify( Slapi_PBlock *pb )
 	int					ignored_some_mods = 0;
 	int					ignored_some_mods = 0;
 	int                 has_password_mod = 0; /* number of password mods */
 	int                 has_password_mod = 0; /* number of password mods */
 	char				*old_pw = NULL;	/* remember the old password */
 	char				*old_pw = NULL;	/* remember the old password */
-	char				*dn;
+	char				*dn = NULL;
 
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
 
 
@@ -161,6 +161,7 @@ do_modify( Slapi_PBlock *pb )
 			op_shared_log_error_access (pb, "MOD", "???", "decoding error");
 			op_shared_log_error_access (pb, "MOD", "???", "decoding error");
     		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
     		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
     		    NULL );
     		    NULL );
+    		slapi_ch_free_string(&dn);
     		return;
     		return;
     	}
     	}
 	}
 	}
@@ -186,7 +187,9 @@ do_modify( Slapi_PBlock *pb )
 			op_shared_log_error_access (pb, "MOD", dn, "decoding error");
 			op_shared_log_error_access (pb, "MOD", dn, "decoding error");
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 							  "decoding error", 0, NULL );
 							  "decoding error", 0, NULL );
+			ber_bvecfree(mod->mod_bvalues);
 			slapi_ch_free((void **)&mod);
 			slapi_ch_free((void **)&mod);
+			slapi_ch_free_string(&type);
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 		mod->mod_op = long_mod_op;
 		mod->mod_op = long_mod_op;

+ 4 - 4
ldap/servers/slapd/modrdn.c

@@ -66,10 +66,10 @@ do_modrdn( Slapi_PBlock *pb )
 {
 {
 	Slapi_Operation *operation;
 	Slapi_Operation *operation;
 	BerElement	*ber;
 	BerElement	*ber;
-	char		*dn, *newsuperior = NULL;
+	char		*dn = NULL, *newsuperior = NULL;
 	char        *newrdn = NULL;
 	char        *newrdn = NULL;
-	int			err, deloldrdn;
-	unsigned long	len;
+	int			err = 0, deloldrdn = 0;
+	unsigned long	len = 0;
 
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
 
 
@@ -99,7 +99,7 @@ do_modrdn( Slapi_PBlock *pb )
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 		    "unable to decode DN, newRDN, or deleteOldRDN parameters",
 		    "unable to decode DN, newRDN, or deleteOldRDN parameters",
 		    0, NULL );
 		    0, NULL );
-		return;
+        goto free_and_return;
 	}
 	}
 
 
 	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) {
 	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) {