From 5265ce7837a185977f71bcb39a41b57492e24964 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Feb 2001 19:22:02 +0000 Subject: Added total memory allocated counter to talloc, so we can tell if a talloc pool is getting bloated. Also added a talloc_zero function to return zeroed memory. Added debug in rpc_server/srv_pipe_hnd.c so we know when a talloc pool is being freed. Syncup with srv_pipe_hnd.c from 2.2 so we are freeing memory at the same time. Jeremy. (This used to be commit d3a56c6042acf037bbd53de88d7636a5803ead20) --- source3/include/proto.h | 16 +++++- source3/include/talloc.h | 1 + source3/lib/talloc.c | 22 ++++++++ source3/rpc_parse/parse_lsa.c | 10 ++-- source3/rpc_parse/parse_misc.c | 103 +++++++++++++++++++++++--------------- source3/rpc_parse/parse_spoolss.c | 4 +- source3/rpc_server/srv_pipe_hnd.c | 36 ++++++++----- source3/smbd/process.c | 2 +- 8 files changed, 134 insertions(+), 60 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index b525b039ff..bcde386362 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -367,6 +367,8 @@ TALLOC_CTX *talloc_init(void); void *talloc(TALLOC_CTX *t, size_t size); void talloc_destroy_pool(TALLOC_CTX *t); void talloc_destroy(TALLOC_CTX *t); +size_t talloc_pool_size(TALLOC_CTX *t); +void *talloc_zero(TALLOC_CTX *t, size_t size); /*The following definitions come from lib/time.c */ @@ -2398,7 +2400,11 @@ BOOL lsa_io_r_open_secret(char *desc, LSA_R_OPEN_SECRET *r_c, prs_struct *ps, in /*The following definitions come from rpc_parse/parse_misc.c */ -void parse_talloc_free(void); +TALLOC_CTX *get_current_rpc_talloc(void); +void set_current_rpc_talloc( TALLOC_CTX *ctx); +void main_loop_talloc_free(void); +TALLOC_CTX *main_loop_talloc_get(void); +TALLOC_CTX *get_talloc_ctx(void); BOOL smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth); BOOL smb_io_lookup_level(char *desc, LOOKUP_LEVEL *level, prs_struct *ps, int depth); uint32 get_enum_hnd(ENUM_HND *enh); @@ -3311,6 +3317,14 @@ BOOL wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int BOOL api_netdfs_rpc(pipes_struct *p); +/*The following definitions come from rpc_server/srv_dfs_nt.c */ + +uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u); +uint32 _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u); +uint32 _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u, DFS_R_DFS_REMOVE *r_u); +uint32 _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u); +uint32 _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u, DFS_R_DFS_GET_INFO *r_u); + /*The following definitions come from rpc_server/srv_lsa.c */ #if OLD_NTDOMAIN diff --git a/source3/include/talloc.h b/source3/include/talloc.h index 85a722d080..32b0f28ae6 100644 --- a/source3/include/talloc.h +++ b/source3/include/talloc.h @@ -36,6 +36,7 @@ struct talloc_chunk { typedef struct { struct talloc_chunk *list; + size_t total_alloc_size; } TALLOC_CTX; #endif diff --git a/source3/lib/talloc.c b/source3/lib/talloc.c index a04bd2561b..854a230a0e 100644 --- a/source3/lib/talloc.c +++ b/source3/lib/talloc.c @@ -47,6 +47,7 @@ TALLOC_CTX *talloc_init(void) if (!t) return NULL; t->list = NULL; + t->total_alloc_size = 0; return t; } @@ -82,6 +83,7 @@ void *talloc(TALLOC_CTX *t, size_t size) c->alloc_size = 0; c->total_size = asize; t->list = c; + t->total_alloc_size += asize; } p = ((char *)t->list->ptr) + t->list->alloc_size; @@ -107,6 +109,7 @@ void talloc_destroy_pool(TALLOC_CTX *t) } t->list = NULL; + t->total_alloc_size = 0; } /* destroy a whole pool including the context */ @@ -117,3 +120,22 @@ void talloc_destroy(TALLOC_CTX *t) talloc_destroy_pool(t); free(t); } + +/* return the current total size of the pool. */ +size_t talloc_pool_size(TALLOC_CTX *t) +{ + if (!t->list) + return 0; + return t->total_alloc_size; +} + +/* talloc and zero memory. */ +void *talloc_zero(TALLOC_CTX *t, size_t size) +{ + void *p = talloc(t, size); + + if (p) + memset(p, '\0', size); + + return p; +} diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index a33c759473..d86df0ee11 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -708,7 +708,7 @@ static BOOL lsa_io_dom_query_2(char *desc, DOM_QUERY_2 *d_q, prs_struct *ps, int return False; if (UNMARSHALLING(ps)) { - d_q->auditsettings = (uint32 *)talloc(ps->mem_ctx, d_q->count2 * sizeof(uint32)); + d_q->auditsettings = (uint32 *)talloc_zero(ps->mem_ctx, d_q->count2 * sizeof(uint32)); } if (d_q->auditsettings == NULL) { @@ -829,13 +829,13 @@ void init_lsa_sid_enum(TALLOC_CTX *mem_ctx, LSA_SID_ENUM *sen, if (num_entries == 0) return; - if ((sen->ptr_sid = (uint32 *)talloc(mem_ctx, num_entries * + if ((sen->ptr_sid = (uint32 *)talloc_zero(mem_ctx, num_entries * sizeof(uint32))) == NULL) { DEBUG(3, ("init_lsa_sid_enum(): out of memory for ptr_sid\n")); return; } - if ((sen->sid = (DOM_SID2 *)talloc(mem_ctx, num_entries * + if ((sen->sid = (DOM_SID2 *)talloc_zero(mem_ctx, num_entries * sizeof(DOM_SID2))) == NULL) { DEBUG(3, ("init_lsa_sid_enum(): out of memory for sids\n")); return; @@ -1070,13 +1070,13 @@ void init_q_lookup_names(TALLOC_CTX *mem_ctx, LSA_Q_LOOKUP_NAMES *q_l, q_l->num_entries2 = num_names; q_l->lookup_level = 1; - if ((q_l->uni_name = (UNISTR2 *)talloc( + if ((q_l->uni_name = (UNISTR2 *)talloc_zero( mem_ctx, num_names * sizeof(UNISTR2))) == NULL) { DEBUG(3, ("init_q_lookup_names(): out of memory\n")); return; } - if ((q_l->hdr_name = (UNIHDR *)talloc( + if ((q_l->hdr_name = (UNIHDR *)talloc_zero( mem_ctx, num_names * sizeof(UNIHDR))) == NULL) { DEBUG(3, ("init_q_lookup_names(): out of memory\n")); return; diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 329683d23a..0a65c09493 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -26,18 +26,66 @@ extern int DEBUGLEVEL; -static TALLOC_CTX *parse_misc_talloc = NULL; +/**************************************************************************** + A temporary TALLOC context for things like unistrs, that is valid for + the life of a complete RPC call. +****************************************************************************/ -/******************************************************************* a +static TALLOC_CTX *current_rpc_talloc = NULL; + +TALLOC_CTX *get_current_rpc_talloc(void) +{ + return current_rpc_talloc; +} + +void set_current_rpc_talloc( TALLOC_CTX *ctx) +{ + current_rpc_talloc = ctx; +} + +static TALLOC_CTX *main_loop_talloc = NULL; + +/******************************************************************* free up temporary memory - called from the main loop ********************************************************************/ -void parse_talloc_free(void) +void main_loop_talloc_free(void) { - if (!parse_misc_talloc) + if (!main_loop_talloc) return; - talloc_destroy(parse_misc_talloc); - parse_misc_talloc = NULL; + talloc_destroy(main_loop_talloc); + main_loop_talloc = NULL; +} + +/******************************************************************* + Get a talloc context that is freed in the main loop... +********************************************************************/ + +TALLOC_CTX *main_loop_talloc_get(void) +{ + if (!main_loop_talloc) { + main_loop_talloc = talloc_init(); + if (!main_loop_talloc) + smb_panic("main_loop_talloc: malloc fail\n"); + } + + return main_loop_talloc; +} + +/******************************************************************* + Try and get a talloc context. Get the rpc one if possible, else + get the main loop one. The main loop one is more dangerous as it + goes away between packets, the rpc one will stay around for as long + as a current RPC lasts. +********************************************************************/ + +TALLOC_CTX *get_talloc_ctx(void) +{ + TALLOC_CTX *tc = get_current_rpc_talloc(); + + if (tc) + return tc; + return main_loop_talloc_get(); } /******************************************************************* @@ -483,19 +531,14 @@ void init_unistr(UNISTR *str, const char *buf) len = strlen(buf) + 1; - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_UNISTRLEN) len = MAX_UNISTRLEN; len *= sizeof(uint16); - str->buffer = (uint16 *)talloc(parse_misc_talloc, len); + str->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len); if (str->buffer == NULL) smb_panic("init_unistr: malloc fail\n"); - memset(str->buffer, '\0', len); - /* store the string (null-terminated copy) */ dos_struni2((char *)str->buffer, buf, len); } @@ -527,15 +570,12 @@ BOOL smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth) static void create_buffer3(BUFFER3 *str, size_t len) { - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_BUFFERLEN) len = MAX_BUFFERLEN; - str->buffer = talloc(parse_misc_talloc, len); + str->buffer = talloc_zero(get_talloc_ctx(), len); if (str->buffer == NULL) - smb_panic("create_buffer3: malloc fail\n"); + smb_panic("create_buffer3: talloc fail\n"); } @@ -673,14 +713,11 @@ void init_buffer2(BUFFER2 *str, uint8 *buf, int len) str->buf_len = buf != NULL ? len : 0; if (buf != NULL) { - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_BUFFERLEN) len = MAX_BUFFERLEN; - str->buffer = talloc(parse_misc_talloc, len); + str->buffer = talloc_zero(get_talloc_ctx(), len); if (str->buffer == NULL) - smb_panic("init_buffer2: malloc fail\n"); + smb_panic("init_buffer2: talloc fail\n"); memcpy(str->buffer, buf, MIN(str->buf_len, len)); } } @@ -767,17 +804,14 @@ void copy_unistr2(UNISTR2 *str, UNISTR2 *from) if (str->buffer == NULL) { size_t len = from->uni_max_len * sizeof(uint16); - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_UNISTRLEN) len = MAX_UNISTRLEN; len *= sizeof(uint16); - str->buffer = (uint16 *)talloc(parse_misc_talloc, len); + str->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len); if ((str->buffer == NULL) && (len > 0 )) { - smb_panic("copy_unistr2: malloc fail\n"); + smb_panic("copy_unistr2: talloc fail\n"); return; } } @@ -801,12 +835,9 @@ void init_string2(STRING2 *str, char *buf, int len) /* store the string */ if(len != 0) { - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_STRINGLEN) alloc_len = MAX_STRINGLEN; - str->buffer = talloc(parse_misc_talloc, alloc_len); + str->buffer = talloc_zero(get_talloc_ctx(), alloc_len); if (str->buffer == NULL) smb_panic("init_string2: malloc fail\n"); memcpy(str->buffer, buf, len); @@ -869,14 +900,11 @@ void init_unistr2(UNISTR2 *str, const char *buf, size_t len) str->undoc = 0; str->uni_str_len = (uint32)len; - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - if (len < MAX_UNISTRLEN) len = MAX_UNISTRLEN; len *= sizeof(uint16); - str->buffer = (uint16 *)talloc(parse_misc_talloc, len); + str->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len); if ((str->buffer == NULL) && (len > 0)) { smb_panic("init_unistr2: malloc fail\n"); @@ -917,11 +945,8 @@ void init_unistr2_from_unistr (UNISTR2 *to, UNISTR *from) to->undoc = 0; to->uni_str_len = i; - if (!parse_misc_talloc) - parse_misc_talloc = talloc_init(); - /* allocate the space and copy the string buffer */ - to->buffer = (uint16 *)talloc(parse_misc_talloc, sizeof(uint16)*(to->uni_str_len)); + to->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), sizeof(uint16)*(to->uni_str_len)); if (to->buffer == NULL) smb_panic("init_unistr2_from_unistr: malloc fail\n"); memcpy(to->buffer, from->buffer, to->uni_max_len*sizeof(uint16)); diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 0961cda195..bb8c818421 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -401,10 +401,10 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data, /* Tallocate memory for string */ - DEBUG(0, ("** tallocating memory\n")); + DEBUG(10, ("** tallocating memory\n")); data->notify_data.data.string = (uint16 *) - talloc(ps->mem_ctx, x * 2); + talloc_zero(ps->mem_ctx, x * 2); if (!data->notify_data.data.string) return False; diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index b8ee235185..3b60c78ade 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -485,14 +485,6 @@ static ssize_t process_complete_pdu(pipes_struct *p) char *data_p = (char *)&p->in_data.current_in_pdu[0]; BOOL reply = False; - if (p->mem_ctx) { - talloc_destroy_pool(p->mem_ctx); - } else { - p->mem_ctx = talloc_init(); - if (p->mem_ctx == NULL) - p->fault_state = True; - } - if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", p->name )); @@ -713,7 +705,7 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; - return data_returned; + goto out; } /* @@ -727,9 +719,10 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) { /* - * We have sent all possible data. Return 0. + * We have sent all possible data, return 0. */ - return 0; + data_returned = 0; + goto out; } /* @@ -748,6 +741,26 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, memcpy( data, p->out_data.current_pdu, (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; + + out: + + if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) { + /* + * We have copied all possible data into the current_pdu. This RPC is finished. + * Reset the talloc context to free any allocated data from this RPC. + */ + + if (p->mem_ctx) { + DEBUG(3,("read_from_pipe: destroying talloc pool of size %u\n", talloc_pool_size(p->mem_ctx) )); + talloc_destroy_pool(p->mem_ctx); + } else { + p->mem_ctx = talloc_init(); + if (p->mem_ctx == NULL) + p->fault_state = True; + } + + } + return data_returned; } @@ -872,5 +885,4 @@ pipes_struct *get_rpc_pipe(int pnum) return NULL; } - #undef OLD_NTDOMAIN diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 461fa99f39..f8fde41b77 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1209,7 +1209,7 @@ void smbd_process(void) /* free up temporary memory */ lp_talloc_free(); - parse_talloc_free(); + main_loop_talloc_free(); while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) -- cgit