Author: nhosoi
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv9625
Modified Files: vattr.c Log Message: Resolves: #193724 Summary: "nested" filtered roles result in deadlock Description: Function slapi_vattr_values_get_sp used to use the context allocated on the stack. Changed it to call vattr_context_new to set the locally created pblock (local_pb). The pblock is used to pass the context loop info as the stack gets deeper to prevent the stack overflow. At the end of this function slapi_vattr_values_get_sp, slapi_pblock_destroy is called if the context is local (use_local_ctx). The function cleans up pb_vattr_context internally.
Index: vattr.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/vattr.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- vattr.c 12 Oct 2007 18:03:42 -0000 1.7 +++ vattr.c 1 Nov 2007 20:24:07 -0000 1.8 @@ -630,163 +630,162 @@ */ SLAPI_DEPRECATED int slapi_vattr_values_get_sp(vattr_context *c, - /* Entry we're interested in */ Slapi_Entry *e, - /* attr type name */ char *type, - /* pointer to result set */ Slapi_ValueSet** results, - int *type_name_disposition, - char** actual_type_name, int flags, - int *buffer_flags) -{ - - PRBool use_local_ctx=PR_FALSE; - vattr_context ctx; - int rc = 0; - int sp_bit = 0; /* Set if an SP supplied an answer */ - vattr_sp_handle_list *list = NULL; - - vattr_get_thang my_get = {0}; - - if (c != NULL) { - rc = vattr_context_grok(&c); - if (0 != rc) { - if(!vattr_context_is_loop_msg_displayed(&c)) - { - /* Print a handy error log message */ - LDAPDebug(LDAP_DEBUG_ANY,"Detected virtual attribute loop in get on entry %s, attribute %s\n", slapi_entry_get_dn_const(e), type, 0); - vattr_context_set_loop_msg_displayed(&c); - } - return rc; - } - } else { - use_local_ctx=PR_TRUE; - ctx.vattr_context_loop_count=1; - ctx.error_displayed = 0; - } - - /* For attributes which are in the entry, we just need to get to the Slapi_Attr structure and yank out the slapi_value_set - structure. We either return a pointer directly to it, or we copy it, depending upon whether the caller asked us to try to - avoid copying. - */ - - /* First grok the entry, and remember what we saw. This call does no more than walk down the entry attribute list, do some string compares and copy pointers. */ - vattr_helper_get_entry_conts(e,type, &my_get); - /* Having done that, we now consult the attribute map to find service providers who are interested */ - /* Look for attribute in the map */ - if(!(flags & SLAPI_REALATTRS_ONLY)) - { - list = vattr_map_sp_getlist(type); - if (list) { - vattr_sp_handle *current_handle = NULL; - void *hint = NULL; - /* first lets consult the cache to save work */ - int cache_status; - - cache_status = - slapi_entry_vattrcache_find_values_and_type(e, type, - results, - actual_type_name); - switch(cache_status) - { - case SLAPI_ENTRY_VATTR_RESOLVED_EXISTS: /* cached vattr */ - { - sp_bit = 1; - - /* Complete analysis of type matching */ - if ( 0 == slapi_attr_type_cmp( type , *actual_type_name, SLAPI_TYPE_CMP_EXACT) ) - { - *type_name_disposition = SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_EXACTLY_OR_ALIAS; - } else { - *type_name_disposition = SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE; - } - - break; - } - - case SLAPI_ENTRY_VATTR_RESOLVED_ABSENT: /* does not exist */ - break; /* look in entry */ - - case SLAPI_ENTRY_VATTR_NOT_RESOLVED: /* not resolved */ - default: /* any other result, resolve */ - { - for (current_handle = vattr_map_sp_first(list,&hint); current_handle; current_handle = vattr_map_sp_next(current_handle,&hint)) - { - if (use_local_ctx) - { - rc = vattr_call_sp_get_value(current_handle,&ctx,e,&my_get,type,results,type_name_disposition,actual_type_name,flags,buffer_flags, hint); - } - else - { - /* call this SP */ - rc = vattr_call_sp_get_value(current_handle,c,e,&my_get,type,results,type_name_disposition,actual_type_name,flags,buffer_flags, hint); - } - - if (0 == rc) - { - sp_bit = 1; - break; - } - } - - if(!sp_bit) - { - /* clean up, we have failed and must now examine the - * entry itself - * But first lets cache the no result - * Creates the type (if necessary). - */ - slapi_entry_vattrcache_merge_sv(e, type, NULL ); - - } - else - { - /* - * we need to cache the virtual attribute - * creates the type (if necessary) and dups - * results. - */ - slapi_entry_vattrcache_merge_sv(e, *actual_type_name, - *results ); - } - - break; - } - } - } - } - /* If no SP supplied the answer, take it from the entry */ - if (!sp_bit && !(flags & SLAPI_VIRTUALATTRS_ONLY)) - { - rc = 0; /* reset return code (cause an sp must have failed) */ - *type_name_disposition = my_get.get_name_disposition; - - if (my_get.get_present) { - if (flags & SLAPI_VIRTUALATTRS_REQUEST_POINTERS) { - *results = my_get.get_present_values; - *actual_type_name = my_get.get_type_name; - } else { - *results = valueset_dup(my_get.get_present_values); - if (NULL == *results) { - rc = ENOMEM; - } else { - *actual_type_name = slapi_ch_strdup(my_get.get_type_name); - if (NULL == *actual_type_name) { - rc = ENOMEM; - } - } - } - if (flags & SLAPI_VIRTUALATTRS_REQUEST_POINTERS) { - *buffer_flags = SLAPI_VIRTUALATTRS_RETURNED_POINTERS; - } else { - *buffer_flags = SLAPI_VIRTUALATTRS_RETURNED_COPIES; - } - } else { - rc = SLAPI_VIRTUALATTRS_NOT_FOUND; - } - } - if (!use_local_ctx) { - vattr_context_ungrok(&c); - } - return rc; + /* Entry we're interested in */ Slapi_Entry *e, + /* attr type name */ char *type, + /* pointer to result set */ Slapi_ValueSet** results, + int *type_name_disposition, + char** actual_type_name, int flags, + int *buffer_flags) +{ + PRBool use_local_ctx = PR_FALSE; + Slapi_PBlock *local_pb = NULL; + vattr_context *ctx = NULL; + int rc = 0; + int sp_bit = 0; /* Set if an SP supplied an answer */ + vattr_sp_handle_list *list = NULL; + + vattr_get_thang my_get = {0}; + + if (c != NULL) { + rc = vattr_context_grok(&c); + if (0 != rc) { + if(!vattr_context_is_loop_msg_displayed(&c)) + { + /* Print a handy error log message */ + LDAPDebug(LDAP_DEBUG_ANY, + "Detected virtual attribute loop in get on entry %s, attribute %s\n", + slapi_entry_get_dn_const(e), type, 0); + vattr_context_set_loop_msg_displayed(&c); + } + return rc; + } + ctx = c; + } else { + use_local_ctx = PR_TRUE; + local_pb = slapi_pblock_new(); + ctx = vattr_context_new( local_pb ); + ctx->vattr_context_loop_count = 1; + ctx->error_displayed = 0; + } + + /* For attributes which are in the entry, we just need to get to the Slapi_Attr structure and yank out the slapi_value_set + structure. We either return a pointer directly to it, or we copy it, depending upon whether the caller asked us to try to + avoid copying. + */ + + /* First grok the entry, and remember what we saw. This call does no more than walk down the entry attribute list, do some string compares and copy pointers. */ + vattr_helper_get_entry_conts(e,type, &my_get); + /* Having done that, we now consult the attribute map to find service providers who are interested */ + /* Look for attribute in the map */ + if(!(flags & SLAPI_REALATTRS_ONLY)) + { + list = vattr_map_sp_getlist(type); + if (list) { + vattr_sp_handle *current_handle = NULL; + void *hint = NULL; + /* first lets consult the cache to save work */ + int cache_status; + + cache_status = + slapi_entry_vattrcache_find_values_and_type(e, type, + results, + actual_type_name); + switch(cache_status) + { + case SLAPI_ENTRY_VATTR_RESOLVED_EXISTS: /* cached vattr */ + { + sp_bit = 1; + + /* Complete analysis of type matching */ + if ( 0 == slapi_attr_type_cmp( type , *actual_type_name, SLAPI_TYPE_CMP_EXACT) ) + { + *type_name_disposition = SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_EXACTLY_OR_ALIAS; + } else { + *type_name_disposition = SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE; + } + + break; + } + + case SLAPI_ENTRY_VATTR_RESOLVED_ABSENT: /* does not exist */ + break; /* look in entry */ + + case SLAPI_ENTRY_VATTR_NOT_RESOLVED: /* not resolved */ + default: /* any other result, resolve */ + { + for (current_handle = vattr_map_sp_first(list,&hint); current_handle; current_handle = vattr_map_sp_next(current_handle,&hint)) + { + rc = vattr_call_sp_get_value(current_handle,ctx,e,&my_get,type,results,type_name_disposition,actual_type_name,flags,buffer_flags, hint); + if (0 == rc) + { + sp_bit = 1; + break; + } + } + + if(!sp_bit) + { + /* clean up, we have failed and must now examine the + * entry itself + * But first lets cache the no result + * Creates the type (if necessary). + */ + slapi_entry_vattrcache_merge_sv(e, type, NULL ); + + } + else + { + /* + * we need to cache the virtual attribute + * creates the type (if necessary) and dups + * results. + */ + slapi_entry_vattrcache_merge_sv(e, *actual_type_name, + *results ); + } + + break; + } + } + } + } + /* If no SP supplied the answer, take it from the entry */ + if (!sp_bit && !(flags & SLAPI_VIRTUALATTRS_ONLY)) + { + rc = 0; /* reset return code (cause an sp must have failed) */ + *type_name_disposition = my_get.get_name_disposition; + + if (my_get.get_present) { + if (flags & SLAPI_VIRTUALATTRS_REQUEST_POINTERS) { + *results = my_get.get_present_values; + *actual_type_name = my_get.get_type_name; + } else { + *results = valueset_dup(my_get.get_present_values); + if (NULL == *results) { + rc = ENOMEM; + } else { + *actual_type_name = slapi_ch_strdup(my_get.get_type_name); + if (NULL == *actual_type_name) { + rc = ENOMEM; + } + } + } + if (flags & SLAPI_VIRTUALATTRS_REQUEST_POINTERS) { + *buffer_flags = SLAPI_VIRTUALATTRS_RETURNED_POINTERS; + } else { + *buffer_flags = SLAPI_VIRTUALATTRS_RETURNED_COPIES; + } + } else { + rc = SLAPI_VIRTUALATTRS_NOT_FOUND; + } + } + if (use_local_ctx) { + /* slapi_pblock_destroy cleans up pb_vattr_context, as well */ + slapi_pblock_destroy(local_pb); + } else { + vattr_context_ungrok(&c); + } + return rc; }
/*