The branch, master has been updated via 127352c source4/torture: add talloc_stackframe() via 06731bc source3/netapi: fix only caller which doesn't set up a talloc_stackframe() via d54ebd3 source3/passdb/py_passdb.c: wrap all calls in talloc_stackframe() via 9927233 source3/passdb/py_passdb.c: don't steal from talloc_stackframe(). via 51ec59d source3/torture/pdbtest: allocate talloc_stackframe() via 1f8b574 talloc_stack: abort in developer me if no stackframe on talloc_tos() via fe72740 loadparm: make the source3/ lp_ functions take an explicit TALLOC_CTX *. via c809eec source3/utils/net_conf.c: fix stackframe leak via aa2e02e source3/winbindd/winbindd_pam.c: fix stackframe leak via f3001e8 source3/lib/smbconf/testsuite.c: fix stackframe leak via 15faffc source3/registry/reg_backend_db.c: fix stackframe leak via 5716570 source3/winbindd/idmap_tdb_common.c: fix stackframe leak via 32c69e6 source3/rpc_server/svcctl/srv_svcctl_reg.c: fix stackframe leak via bdc59fb source3/modules/vfs_xattr_tdb.c: fix stackframe leak via a620fc0 lib/util/modules.c: fix stackframe leak. via 2314c60 source3/winbindd/winbindd_util.c: fix stackframe leak via 7a65910 nt_printing_tdb_migrate(): fix stackframe leak. via dcec7c1 source3/client/client.c: fix stackframe leak. via 634a63d smbpasswd: always free frame. via 84fb37f talloc_stack: report lazy freeing (panic if DEVELOPER). via f9b51ff talloc_stack: always include the location when creating a talloc_stackframe(). via 311281c talloc_stack: handle more than one talloc_stackframe_pool() via 4f33187 talloc: don't allow a talloc_pool inside a talloc_pool. via 8893215 talloc: use a struct for pool headers. from d1a5a5b s3-linux-aio: Fix error handling
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 127352c78c0328d59d742f0b4520ebaac6307854 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:28 2012 +0930 source4/torture: add talloc_stackframe() We need a stackframe to call lp_load(). Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> Autobuild-User(master): Rusty Russell <ru...@rustcorp.com.au> Autobuild-Date(master): Wed Jul 18 09:31:07 CEST 2012 on sn-devel-104 commit 06731bc28f5bff963f75451a0d7dd7445e94407c Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:28 2012 +0930 source3/netapi: fix only caller which doesn't set up a talloc_stackframe() libnetapi_free() needs a stackframe too; looked like Andrew and Günther missed this in a37de9a95974c138d264d9cb0c7829bb426bb2d6. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit d54ebd36cc95ae13844bd00d5bbb2e3ff1a06285 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:28 2012 +0930 source3/passdb/py_passdb.c: wrap all calls in talloc_stackframe() dbwrap needs it. Some calls were already wrapped, but they checked the talloc_stackframe() return unnecessarily: it can never be NULL. This is the coccinelle patch I used: // Add in a stackframe to every function: be sure to free it on (every) return @rule0@ identifier func; @@ func(...) { +TALLOC_CTX *frame = talloc_stackframe(); <... +talloc_free(frame); return ...; ...> } // Get rid of tframe allocation/frees, replace usage with frame. @rule1@ identifier func; identifier oldframe; @@ func(...) { ... -TALLOC_CTX *oldframe; ... -if ((oldframe = talloc_stackframe()) == NULL) { - ... -} <... -talloc_free(oldframe); ...> } // Get rid of tframe (variant 2) @rule2@ identifier func; identifier oldframe; @@ func(...) { ... -TALLOC_CTX *oldframe; ... -oldframe = talloc_stackframe(); -if (oldframe == NULL) { - ... -} <... -talloc_free(oldframe); ...> } // Change tframe to frame @rule3@ identifier func; @@ func(...) { <... -tframe +frame ...> } Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 99272331c60afa900852d996196b434ecd897287 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:28 2012 +0930 source3/passdb/py_passdb.c: don't steal from talloc_stackframe(). If you want a stack-style allocation, use talloc_stackframe(). If you don't, don't use it. In particular, talloc_stackframe() here is actually inside a pool, and stealing from pools is a bad idea. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 51ec59db10306fd90211c237fd672acf3ab3304a Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:28 2012 +0930 source3/torture/pdbtest: allocate talloc_stackframe() Avoid talloc_tos() without a stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 1f8b574adb10397ca4b9dc4a55281d3afaaeabfc Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:27 2012 +0930 talloc_stack: abort in developer me if no stackframe on talloc_tos() Don't tolerate leaks in developer mode. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit fe72740e8221575921c22030d6d4fcb19201b03b Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 15:07:23 2012 +0930 loadparm: make the source3/ lp_ functions take an explicit TALLOC_CTX *. They use talloc_tos() internally: hoist that up to the callers, some of whom don't want to us talloc_tos(). A simple patch, but hits a lot of files. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit c809eec53fb1d2a36909e4934dff349f91e3359e Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:09:31 2012 +0930 source3/utils/net_conf.c: fix stackframe leak net_conf_wrap_function() doesn't free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit aa2e02e6846c4fa8199ebafbe6b9e050df8af16b Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:08:31 2012 +0930 source3/winbindd/winbindd_pam.c: fix stackframe leak check_info3_in_group() doesn't always free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit f3001e808c3b1ea35358f41154360709642cf282 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:07:31 2012 +0930 source3/lib/smbconf/testsuite.c: fix stackframe leak Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 15faffc53752f27c550c305435a1d7e1ea58514f Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:06:31 2012 +0930 source3/registry/reg_backend_db.c: fix stackframe leak regdb_store_values_internal() doesn't always free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 5716570cbc1db1bf0d60441622f79ac934443232 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:05:31 2012 +0930 source3/winbindd/idmap_tdb_common.c: fix stackframe leak idmap_tdb_common_sid_to_unixid() doesn't always free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 32c69e6e2a089812610599ee9e0e832d2ffe195a Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:04:31 2012 +0930 source3/rpc_server/svcctl/srv_svcctl_reg.c: fix stackframe leak svcctl_init_winreg() doesn't free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit bdc59fb538345d9571554dfef79469fa2c325c90 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:03:31 2012 +0930 source3/modules/vfs_xattr_tdb.c: fix stackframe leak xattr_tdb_getxattr() doesn't free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit a620fc0372a8c493c8d4800acc42cc630acebcb4 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:02:31 2012 +0930 lib/util/modules.c: fix stackframe leak. do_smb_load_module() doesn't free its stackframe on success. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 2314c606297218b8e16bb42b181c1ea175cf710a Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:01:31 2012 +0930 source3/winbindd/winbindd_util.c: fix stackframe leak winbindd_can_contact_domain() doesn't always free its stackframe. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 7a6591037b22773c03a7592230f33832b0775237 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 05:00:31 2012 +0930 nt_printing_tdb_migrate(): fix stackframe leak. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit dcec7c1f71937ad301be95050fb0e69aede7648c Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:59:31 2012 +0930 source3/client/client.c: fix stackframe leak. do_message_op() doesn't free its stackframe in various paths. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 634a63d934db6f01fd8c2584af9ab05e05762a0d Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:58:31 2012 +0930 smbpasswd: always free frame. We're about to exit, so it doesn't really matter, but might as well unify the paths. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 84fb37fe372bc22e0a3ceca8030bff459225044a Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:57:31 2012 +0930 talloc_stack: report lazy freeing (panic if DEVELOPER). talloc_stackframe() stacks, so if you forget to free one, the outer one will free it. However, it's not a good idea to rely too heavily on this behaviour: it can lead to delays in the release of memory or destructors. I had an elaborate hack to make sure every talloc_stackframe() was freed in the exact same function it was allocated, however all bugs it caught were simply lazy freeing, so this patch just checks for that. This doesn't check for stackframes we don't free up on exit: that would be nice, but uncovers some uncomfortable (but probably harmless) cases. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit f9b51ff33e10aa126de848072e98b0bf36a7dbc7 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:56:31 2012 +0930 talloc_stack: always include the location when creating a talloc_stackframe(). Much better for debugging. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 311281c2c550b71ec4d8b2fc7329a1dfe5af82b0 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:55:31 2012 +0930 talloc_stack: handle more than one talloc_stackframe_pool() The only reason we make one stackframe parent of the next is so we use our parent's pool. That doesn't make sense if we're a new pool, and wouldn't work anyway. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 4f331872bc783445c709e5fe4846b8687e274953 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:54:31 2012 +0930 talloc: don't allow a talloc_pool inside a talloc_pool. We explicitly call free() on a pool which falls to zero, assuming it's not inside another pool (we crash). Check on creation and explicitly document this case. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 8893215aaf714154c190c66bf7d1ce568118ec39 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Wed Jul 18 04:53:31 2012 +0930 talloc: use a struct for pool headers. This neatens the code a bit (we should do a similar thing for all the TALLOC_CHUNK macros). Two subtler changes: (1) As a result of the struct, we actually pack object_count into the talloc header on 32-bit platforms (since the header is 40 bytes, but needs to be 16-byte aligned). (2) I avoid VALGRIND_MAKE_MEM_UNDEFINED on memmove when we resize the only entry in a pool; that's done later anyway. With -O2 on my 11.04 Ubuntu 32-bit x86 laptop, the talloc_pool speed as measured by testsuite.c actually increases 10%. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> ----------------------------------------------------------------------- Summary of changes: lib/talloc/talloc.c | 201 +++--- lib/talloc/talloc.h | 3 +- lib/talloc/testsuite.c | 2 +- lib/util/debug_s3.c | 2 +- lib/util/modules.c | 3 +- lib/util/talloc_stack.c | 51 +- lib/util/talloc_stack.h | 9 +- source3/auth/auth_util.c | 8 +- source3/auth/pampass.c | 2 +- source3/auth/user_util.c | 4 +- source3/client/client.c | 22 +- source3/groupdb/mapping.c | 20 +- source3/include/proto.h | 162 ++-- source3/lib/netapi/netapi.c | 4 + source3/lib/netapi/serverinfo.c | 4 +- source3/lib/smbconf/testsuite.c | 1 + source3/lib/smbldap.c | 3 +- source3/lib/sysquotas.c | 4 +- source3/lib/util.c | 4 +- source3/libnet/libnet_dssync_passdb.c | 4 +- source3/libnet/libnet_samsync_ldif.c | 40 +- source3/libnet/libnet_samsync_passdb.c | 4 +- source3/modules/vfs_default.c | 2 +- source3/modules/vfs_dfs_samba4.c | 2 +- source3/modules/vfs_expand_msdfs.c | 2 +- source3/modules/vfs_fileid.c | 2 +- source3/modules/vfs_full_audit.c | 4 +- source3/modules/vfs_recycle.c | 2 +- source3/modules/vfs_xattr_tdb.c | 4 +- source3/nmbd/nmbd.c | 4 +- source3/nmbd/nmbd_sendannounce.c | 7 +- source3/nmbd/nmbd_serverlistdb.c | 2 +- source3/nmbd/nmbd_winsserver.c | 2 +- source3/nmbd/nmbd_workgroupdb.c | 2 +- source3/param/loadparm.c | 115 ++-- source3/param/service.c | 4 +- source3/passdb/pdb_interface.c | 8 +- source3/passdb/pdb_ipa.c | 8 +- source3/passdb/pdb_ldap.c | 54 +- source3/passdb/pdb_ldap_util.c | 6 +- source3/passdb/pdb_smbpasswd.c | 5 +- source3/passdb/pdb_tdb.c | 2 +- source3/passdb/py_passdb.c | 1025 +++++++++++------------ source3/passdb/secrets.c | 2 +- source3/printing/load.c | 2 +- source3/printing/notify.c | 16 +- source3/printing/nt_printing.c | 10 +- source3/printing/nt_printing_ads.c | 2 +- source3/printing/nt_printing_migrate_internal.c | 1 + source3/printing/nt_printing_os2.c | 2 +- source3/printing/print_cups.c | 28 +- source3/printing/print_generic.c | 26 +- source3/printing/print_iprint.c | 24 +- source3/printing/printing.c | 38 +- source3/printing/printspoolss.c | 5 +- source3/printing/spoolssd.c | 12 +- source3/registry/reg_backend_db.c | 6 +- source3/rpc_server/epmd.c | 5 +- source3/rpc_server/lsasd.c | 6 +- source3/rpc_server/samr/srv_samr_chgpasswd.c | 10 +- source3/rpc_server/samr/srv_samr_nt.c | 14 +- source3/rpc_server/spoolss/srv_spoolss_nt.c | 40 +- source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 97 ++-- source3/rpc_server/svcctl/srv_svcctl_reg.c | 1 + source3/rpc_server/winreg/srv_winreg_nt.c | 10 +- source3/smbd/close.c | 10 +- source3/smbd/conn_idle.c | 3 +- source3/smbd/connection.c | 7 +- source3/smbd/dfree.c | 2 +- source3/smbd/dosmode.c | 2 +- source3/smbd/fake_file.c | 4 +- source3/smbd/lanman.c | 25 +- source3/smbd/mangle.c | 2 +- source3/smbd/message.c | 12 +- source3/smbd/msdfs.c | 41 +- source3/smbd/nttrans.c | 4 +- source3/smbd/open.c | 2 +- source3/smbd/password.c | 2 +- source3/smbd/perfcount.c | 2 +- source3/smbd/process.c | 11 +- source3/smbd/reply.c | 16 +- source3/smbd/server.c | 2 +- source3/smbd/server_reload.c | 8 +- source3/smbd/service.c | 102 ++-- source3/smbd/share_access.c | 19 +- source3/smbd/smb2_find.c | 4 +- source3/smbd/smb2_tcon.c | 7 +- source3/smbd/trans2.c | 40 +- source3/smbd/uid.c | 15 +- source3/torture/cmd_vfs.c | 2 +- source3/torture/pdbtest.c | 4 +- source3/utils/net_conf.c | 2 + source3/utils/net_idmap.c | 3 +- source3/utils/net_sam.c | 15 +- source3/utils/net_usershare.c | 8 +- source3/utils/smbpasswd.c | 12 +- source3/utils/testparm.c | 44 +- source3/web/swat.c | 6 +- source3/winbindd/idmap_ldap.c | 2 +- source3/winbindd/idmap_tdb_common.c | 1 + source3/winbindd/winbindd.c | 8 +- source3/winbindd/winbindd_dual.c | 4 +- source3/winbindd/winbindd_pam.c | 1 + source3/winbindd/winbindd_util.c | 6 +- source4/torture/libnetapi/libnetapi.c | 3 + 105 files changed, 1331 insertions(+), 1308 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index e5fd0d2..18ee548 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -437,49 +437,50 @@ _PUBLIC_ const char *talloc_parent_name(const void *ptr) memory footprint of each talloc chunk by those 16 bytes. */ -#define TALLOC_POOL_HDR_SIZE 16 +union talloc_pool_chunk { + /* This lets object_count nestle into 16-byte padding of talloc_chunk, + * on 32-bit platforms. */ + struct tc_pool_hdr { + struct talloc_chunk c; + unsigned int object_count; + } hdr; + /* This makes it always 16 byte aligned. */ + char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))]; +}; -#define TC_POOL_SPACE_LEFT(_pool_tc) \ - PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \ - (_pool_tc)->pool) +static void *tc_pool_end(union talloc_pool_chunk *pool_tc) +{ + return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size; +} -#define TC_POOL_FIRST_CHUNK(_pool_tc) \ - ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc))) +static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc) +{ + return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool; +} -#define TC_POOLMEM_CHUNK_SIZE(_tc) \ - TC_ALIGN16(TC_HDR_SIZE + (_tc)->size) +static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc) +{ + return pool_tc + 1; +} -#define TC_POOLMEM_NEXT_CHUNK(_tc) \ - ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc))) +/* If tc is inside a pool, this gives the next neighbour. */ +static void *tc_next_chunk(struct talloc_chunk *tc) +{ + return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size); +} /* Mark the whole remaining pool as not accessable */ -#define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \ - if (unlikely(talloc_fill.enabled)) { \ - size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ - char *_fptr = (char *)(_pool_tc)->pool; \ - memset(_fptr, talloc_fill.fill_value, _flen); \ - } \ -} while(0) +static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc) +{ + size_t flen = tc_pool_space_left(pool_tc); + + if (unlikely(talloc_fill.enabled)) { + memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen); + } #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) -/* Mark the whole remaining pool as not accessable */ -#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \ - size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ - char *_fptr = (char *)(_pool_tc)->pool; \ - VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ -} while(0) -#else -#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0) + VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen); #endif - -#define TC_INVALIDATE_POOL(_pool_tc) do { \ - TC_INVALIDATE_FILL_POOL(_pool_tc); \ - TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \ -} while (0) - -static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) -{ - return (unsigned int *)((char *)tc + TC_HDR_SIZE); } /* @@ -489,7 +490,7 @@ static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, size_t size) { - struct talloc_chunk *pool_ctx = NULL; + union talloc_pool_chunk *pool_ctx = NULL; size_t space_left; struct talloc_chunk *result; size_t chunk_size; @@ -499,17 +500,17 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, } if (parent->flags & TALLOC_FLAG_POOL) { - pool_ctx = parent; + pool_ctx = (union talloc_pool_chunk *)parent; } else if (parent->flags & TALLOC_FLAG_POOLMEM) { - pool_ctx = (struct talloc_chunk *)parent->pool; + pool_ctx = (union talloc_pool_chunk *)parent->pool; } if (pool_ctx == NULL) { return NULL; } - space_left = TC_POOL_SPACE_LEFT(pool_ctx); + space_left = tc_pool_space_left(pool_ctx); /* * Align size to 16 bytes @@ -520,18 +521,18 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, return NULL; } - result = (struct talloc_chunk *)pool_ctx->pool; + result = (struct talloc_chunk *)pool_ctx->hdr.c.pool; #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) VALGRIND_MAKE_MEM_UNDEFINED(result, size); #endif - pool_ctx->pool = (void *)((char *)result + chunk_size); + pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size); result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; result->pool = pool_ctx; - *talloc_pool_objectcount(pool_ctx) += 1; + pool_ctx->hdr.object_count++; return result; } @@ -595,21 +596,27 @@ static inline void *__talloc(const void *context, size_t size) _PUBLIC_ void *talloc_pool(const void *context, size_t size) { - void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); - struct talloc_chunk *tc; + union talloc_pool_chunk *pool_tc; + void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size); if (unlikely(result == NULL)) { return NULL; } - tc = talloc_chunk_from_ptr(result); - - tc->flags |= TALLOC_FLAG_POOL; - tc->pool = TC_POOL_FIRST_CHUNK(tc); + pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result); + if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) { + /* We don't handle this correctly, so fail. */ + talloc_log("talloc: cannot allocate pool off another pool %s\n", + talloc_get_name(context)); + talloc_free(result); + return NULL; + } + pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL; + pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc); - *talloc_pool_objectcount(tc) = 1; + pool_tc->hdr.object_count = 1; - TC_INVALIDATE_POOL(tc); + tc_invalidate_pool(pool_tc); return result; } @@ -712,12 +719,11 @@ static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); static inline void _talloc_free_poolmem(struct talloc_chunk *tc, const char *location) { - struct talloc_chunk *pool; + union talloc_pool_chunk *pool; void *next_tc; - unsigned int *pool_object_count; - pool = (struct talloc_chunk *)tc->pool; - next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + pool = (union talloc_pool_chunk *)tc->pool; + next_tc = tc_next_chunk(tc); tc->flags |= TALLOC_FLAG_FREE; @@ -729,16 +735,15 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc, TC_INVALIDATE_FULL_CHUNK(tc); - pool_object_count = talloc_pool_objectcount(pool); - - if (unlikely(*pool_object_count == 0)) { + if (unlikely(pool->hdr.object_count == 0)) { talloc_abort("Pool object count zero!"); return; } - *pool_object_count -= 1; + pool->hdr.object_count--; - if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) { + if (unlikely(pool->hdr.object_count == 1 + && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) { /* * if there is just one object left in the pool * and pool->flags does not have TALLOC_FLAG_FREE, @@ -746,25 +751,25 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc, * the rest is available for new objects * again. */ - pool->pool = TC_POOL_FIRST_CHUNK(pool); - TC_INVALIDATE_POOL(pool); - } else if (unlikely(*pool_object_count == 0)) { + pool->hdr.c.pool = tc_pool_first_chunk(pool); + tc_invalidate_pool(pool); + } else if (unlikely(pool->hdr.object_count == 0)) { /* * we mark the freed memory with where we called the free * from. This means on a double free error we can report where * the first free came from */ - pool->name = location; + pool->hdr.c.name = location; - TC_INVALIDATE_FULL_CHUNK(pool); + TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c); free(pool); - } else if (pool->pool == next_tc) { + } else if (pool->hdr.c.pool == next_tc) { /* * if pool->pool still points to end of * 'tc' (which is stored in the 'next_tc' variable), * we can reclaim the memory of 'tc'. */ - pool->pool = tc; + pool->hdr.c.pool = tc; } } @@ -854,18 +859,15 @@ static inline int _talloc_free_internal(void *ptr, const char *location) tc->name = location; if (tc->flags & TALLOC_FLAG_POOL) { - unsigned int *pool_object_count; - - pool_object_count = talloc_pool_objectcount(tc); + union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc; - if (unlikely(*pool_object_count == 0)) { + if (unlikely(pool->hdr.object_count == 0)) { talloc_abort("Pool object count zero!"); return 0; } - *pool_object_count -= 1; - - if (unlikely(*pool_object_count == 0)) { + pool->hdr.object_count--; + if (unlikely(pool->hdr.object_count == 0)) { TC_INVALIDATE_FULL_CHUNK(tc); free(tc); } @@ -1380,7 +1382,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons struct talloc_chunk *tc; void *new_ptr; bool malloced = false; - struct talloc_chunk *pool_tc = NULL; + union talloc_pool_chunk *pool_tc = NULL; /* size zero is equivalent to free() */ if (unlikely(size == 0)) { @@ -1409,20 +1411,21 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons return NULL; } - /* don't let anybody try to realloc a talloc_pool */ + /* handle realloc inside a talloc_pool */ if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) { - pool_tc = (struct talloc_chunk *)tc->pool; + pool_tc = (union talloc_pool_chunk *)tc->pool; } #if (ALWAYS_REALLOC == 0) /* don't shrink if we have less than 1k to gain */ if (size < tc->size) { if (pool_tc) { - void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + void *next_tc = tc_next_chunk(tc); TC_INVALIDATE_SHRINK_CHUNK(tc, size); tc->size = size; - if (next_tc == pool_tc->pool) { - pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); + if (next_tc == pool_tc->hdr.c.pool) { + /* note: tc->size has changed, so this works */ + pool_tc->hdr.c.pool = tc_next_chunk(tc); } return ptr; } else if ((tc->size - size) < 1024) { @@ -1455,7 +1458,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons #if ALWAYS_REALLOC if (pool_tc) { new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); - *talloc_pool_objectcount(pool_tc) -= 1; + pool_tc->hdr.object_count--; if (new_ptr == NULL) { new_ptr = malloc(TC_HDR_SIZE+size); @@ -1475,14 +1478,14 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons } #else if (pool_tc) { - void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); - size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc); + void *next_tc = tc_next_chunk(tc); + size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size); size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size); size_t space_needed; size_t space_left; - unsigned int chunk_count = *talloc_pool_objectcount(pool_tc); + unsigned int chunk_count = pool_tc->hdr.object_count; - if (!(pool_tc->flags & TALLOC_FLAG_FREE)) { + if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) { chunk_count -= 1; } @@ -1491,27 +1494,15 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons * optimize for the case where 'tc' is the only * chunk in the pool. */ + char *start = tc_pool_first_chunk(pool_tc); space_needed = new_chunk_size; - space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE; + space_left = (char *)tc_pool_end(pool_tc) - start; if (space_left >= space_needed) { size_t old_used = TC_HDR_SIZE + tc->size; size_t new_used = TC_HDR_SIZE + size; - pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc); -#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) - /* - * we need to prepare the memmove into - * the unaccessable area. - */ - { - size_t diff = PTR_DIFF(tc, pool_tc->pool); - size_t flen = MIN(diff, old_used); - char *fptr = (char *)pool_tc->pool; - VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen); - } -#endif - memmove(pool_tc->pool, tc, old_used); - new_ptr = pool_tc->pool; + new_ptr = start; + memmove(new_ptr, tc, old_used); tc = (struct talloc_chunk *)new_ptr; TC_UNDEFINE_GROW_CHUNK(tc, size); @@ -1521,11 +1512,11 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons * because we want to invalidate the padding * too. */ - pool_tc->pool = new_used + (char *)new_ptr; - TC_INVALIDATE_POOL(pool_tc); + pool_tc->hdr.c.pool = new_used + (char *)new_ptr; + tc_invalidate_pool(pool_tc); /* now the aligned pointer */ - pool_tc->pool = new_chunk_size + (char *)new_ptr; + pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr; goto got_new_ptr; } @@ -1539,19 +1530,19 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons return ptr; } - if (next_tc == pool_tc->pool) { + if (next_tc == pool_tc->hdr.c.pool) { /* * optimize for the case where 'tc' is the last * chunk in the pool. */ space_needed = new_chunk_size - old_chunk_size; - space_left = TC_POOL_SPACE_LEFT(pool_tc); + space_left = tc_pool_space_left(pool_tc); if (space_left >= space_needed) { TC_UNDEFINE_GROW_CHUNK(tc, size); tc->flags &= ~TALLOC_FLAG_FREE; tc->size = size; - pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); + pool_tc->hdr.c.pool = tc_next_chunk(tc); return ptr; } } diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h index 05e6292..e48dc09 100644 --- a/lib/talloc/talloc.h +++ b/lib/talloc/talloc.h @@ -839,7 +839,8 @@ void *talloc_find_parent_bytype(const void *ptr, #type); * talloc pool to a talloc parent outside the pool, the whole pool memory is * not free(3)'ed until that moved chunk is also talloc_free()ed. * - * @param[in] context The talloc context to hang the result off. + * @param[in] context The talloc context to hang the result off (must not + * be another pool). * * @param[in] size Size of the talloc pool. * diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c index 7191703..eaab9d7 100644 --- a/lib/talloc/testsuite.c +++ b/lib/talloc/testsuite.c @@ -848,7 +848,7 @@ static bool test_speed(void) p1 = talloc_size(ctx, loop % 100); p2 = talloc_strdup(p1, "foo bar"); p3 = talloc_size(p1, 300); - talloc_free_children(ctx); + talloc_free(p1); } count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); diff --git a/lib/util/debug_s3.c b/lib/util/debug_s3.c index cfb6755..ccf577f 100644 --- a/lib/util/debug_s3.c +++ b/lib/util/debug_s3.c @@ -30,7 +30,7 @@ bool reopen_logs(void) { if (lp_loaded()) { struct debug_settings settings; - debug_set_logfile(lp_logfile()); + debug_set_logfile(lp_logfile(talloc_tos())); ZERO_STRUCT(settings); settings.max_log_size = lp_max_log_size(); diff --git a/lib/util/modules.c b/lib/util/modules.c index 93fd79b..23298da 100644 --- a/lib/util/modules.c +++ b/lib/util/modules.c @@ -192,6 +192,7 @@ static NTSTATUS do_smb_load_module(const char *subsystem, } if (!init) { + TALLOC_FREE(ctx); return NT_STATUS_UNSUCCESSFUL; } @@ -203,7 +204,7 @@ static NTSTATUS do_smb_load_module(const char *subsystem, module_name, get_friendly_nt_error_msg(status))); dlclose(handle); } - + TALLOC_FREE(ctx); return status; } diff --git a/lib/util/talloc_stack.c b/lib/util/talloc_stack.c index 16e9d74..9c72c80 100644 --- a/lib/util/talloc_stack.c +++ b/lib/util/talloc_stack.c @@ -96,6 +96,17 @@ static int talloc_pop(TALLOC_CTX *frame) (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); int i; + /* Catch lazy frame-freeing. */ + if (ts->talloc_stack[ts->talloc_stacksize-1] != frame) { + DEBUG(0, ("Freed frame %s, expected %s.\n", + talloc_get_name(frame), + talloc_get_name(ts->talloc_stack + [ts->talloc_stacksize-1]))); +#ifdef DEVELOPER + smb_panic("Frame not freed in order."); +#endif + } + for (i=ts->talloc_stacksize-1; i>0; i--) { if (frame == ts->talloc_stack[i]) { break; @@ -115,9 +126,10 @@ static int talloc_pop(TALLOC_CTX *frame) * not explicitly freed. */ -static TALLOC_CTX *talloc_stackframe_internal(size_t poolsize) +static TALLOC_CTX *talloc_stackframe_internal(const char *location, + size_t poolsize) { - TALLOC_CTX **tmp, *top, *parent; + TALLOC_CTX **tmp, *top; struct talloc_stackframe *ts = (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); -- Samba Shared Repository