Commit ff8ae4de authored by Mathieu Parent's avatar Mathieu Parent

New upstream version 2.1.11

parent 170c34b8
_pytalloc_check_type: int (PyObject *, const char *)
_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
_pytalloc_get_ptr: void *(PyObject *)
_pytalloc_get_type: void *(PyObject *, const char *)
pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
pytalloc_BaseObject_check: int (PyObject *)
pytalloc_BaseObject_size: size_t (void)
pytalloc_CObject_FromTallocPtr: PyObject *(void *)
pytalloc_Check: int (PyObject *)
pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
pytalloc_GetBaseObjectType: PyTypeObject *(void)
pytalloc_GetObjectType: PyTypeObject *(void)
pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
pytalloc_steal: PyObject *(PyTypeObject *, void *)
pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
_pytalloc_check_type: int (PyObject *, const char *)
_pytalloc_get_mem_ctx: TALLOC_CTX *(PyObject *)
_pytalloc_get_ptr: void *(PyObject *)
_pytalloc_get_type: void *(PyObject *, const char *)
pytalloc_BaseObject_PyType_Ready: int (PyTypeObject *)
pytalloc_BaseObject_check: int (PyObject *)
pytalloc_BaseObject_size: size_t (void)
pytalloc_Check: int (PyObject *)
pytalloc_GenericObject_reference_ex: PyObject *(TALLOC_CTX *, void *)
pytalloc_GenericObject_steal_ex: PyObject *(TALLOC_CTX *, void *)
pytalloc_GetBaseObjectType: PyTypeObject *(void)
pytalloc_GetObjectType: PyTypeObject *(void)
pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
pytalloc_steal: PyObject *(PyTypeObject *, void *)
pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
_talloc: void *(const void *, size_t)
_talloc_array: void *(const void *, size_t, unsigned int, const char *)
_talloc_free: int (void *, const char *)
_talloc_get_type_abort: void *(const void *, const char *, const char *)
_talloc_memdup: void *(const void *, const void *, size_t, const char *)
_talloc_move: void *(const void *, const void *)
_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
_talloc_realloc: void *(const void *, void *, size_t, const char *)
_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
_talloc_reference_loc: void *(const void *, const void *, const char *)
_talloc_set_destructor: void (const void *, int (*)(void *))
_talloc_steal_loc: void *(const void *, const void *, const char *)
_talloc_zero: void *(const void *, size_t, const char *)
_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
talloc_asprintf: char *(const void *, const char *, ...)
talloc_asprintf_append: char *(char *, const char *, ...)
talloc_asprintf_append_buffer: char *(char *, const char *, ...)
talloc_autofree_context: void *(void)
talloc_check_name: void *(const void *, const char *)
talloc_disable_null_tracking: void (void)
talloc_enable_leak_report: void (void)
talloc_enable_leak_report_full: void (void)
talloc_enable_null_tracking: void (void)
talloc_enable_null_tracking_no_autofree: void (void)
talloc_find_parent_byname: void *(const void *, const char *)
talloc_free_children: void (void *)
talloc_get_name: const char *(const void *)
talloc_get_size: size_t (const void *)
talloc_increase_ref_count: int (const void *)
talloc_init: void *(const char *, ...)
talloc_is_parent: int (const void *, const void *)
talloc_named: void *(const void *, size_t, const char *, ...)
talloc_named_const: void *(const void *, size_t, const char *)
talloc_parent: void *(const void *)
talloc_parent_name: const char *(const void *)
talloc_pool: void *(const void *, size_t)
talloc_realloc_fn: void *(const void *, void *, size_t)
talloc_reference_count: size_t (const void *)
talloc_reparent: void *(const void *, const void *, const void *)
talloc_report: void (const void *, FILE *)
talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
talloc_report_depth_file: void (const void *, int, int, FILE *)
talloc_report_full: void (const void *, FILE *)
talloc_set_abort_fn: void (void (*)(const char *))
talloc_set_log_fn: void (void (*)(const char *))
talloc_set_log_stderr: void (void)
talloc_set_memlimit: int (const void *, size_t)
talloc_set_name: const char *(const void *, const char *, ...)
talloc_set_name_const: void (const void *, const char *)
talloc_show_parents: void (const void *, FILE *)
talloc_strdup: char *(const void *, const char *)
talloc_strdup_append: char *(char *, const char *)
talloc_strdup_append_buffer: char *(char *, const char *)
talloc_strndup: char *(const void *, const char *, size_t)
talloc_strndup_append: char *(char *, const char *, size_t)
talloc_strndup_append_buffer: char *(char *, const char *, size_t)
talloc_test_get_magic: int (void)
talloc_total_blocks: size_t (const void *)
talloc_total_size: size_t (const void *)
talloc_unlink: int (const void *, void *)
talloc_vasprintf: char *(const void *, const char *, va_list)
talloc_vasprintf_append: char *(char *, const char *, va_list)
talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
talloc_version_major: int (void)
talloc_version_minor: int (void)
......@@ -473,10 +473,13 @@ def CHECK_STRUCTURE_MEMBER(conf, structname, member,
def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n'):
'''check if the given cflags are accepted by the compiler
'''
check_cflags = TO_LIST(cflags)
if 'WERROR_CFLAGS' in conf.env:
check_cflags.extend(conf.env['WERROR_CFLAGS'])
return conf.check(fragment=fragment,
execute=0,
type='nolink',
ccflags=cflags,
ccflags=check_cflags,
msg="Checking compiler accepts %s" % cflags)
@conf
......@@ -708,7 +711,9 @@ def SAMBA_CONFIG_H(conf, path=None):
testflags=True)
conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', testflags=True)
conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True)
conf.ADD_CFLAGS('-Werror=format-security -Wformat-security',
testflags=True, prereq_flags='-Wformat')
# This check is because for ldb_search(), a NULL format string
# is not an error, but some compilers complain about that.
if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
......@@ -769,14 +774,15 @@ def CONFIG_PATH(conf, name, default):
conf.env[name] = conf.env['PREFIX'] + default
@conf
def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False):
def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]):
'''add some CFLAGS to the command line
optionally set testflags to ensure all the flags work
'''
prereq_flags = TO_LIST(prereq_flags)
if testflags:
ok_flags=[]
for f in flags.split():
if CHECK_CFLAGS(conf, f):
if CHECK_CFLAGS(conf, [f] + prereq_flags):
ok_flags.append(f)
flags = ok_flags
if not name in conf.env:
......@@ -784,11 +790,12 @@ def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False):
conf.env[name].extend(TO_LIST(flags))
@conf
def ADD_CFLAGS(conf, flags, testflags=False):
def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]):
'''add some CFLAGS to the command line
optionally set testflags to ensure all the flags work
'''
ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags)
ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags,
prereq_flags=prereq_flags)
@conf
def ADD_LDFLAGS(conf, flags, testflags=False):
......
......@@ -115,7 +115,7 @@ def dist(appname='', version=''):
blacklisted = True
if blacklisted:
continue
if os.path.isdir(abspath):
if os.path.isdir(abspath) and not os.path.islink(abspath):
continue
if dstsubdir != '.':
f = dstsubdir + '/' + f
......@@ -182,7 +182,7 @@ def dist(appname='', version=''):
absfile = os.path.join(srcdir, file)
if os.path.isdir(absfile):
if os.path.isdir(absfile) and not os.path.islink(absfile):
destdir = destfile
dir = file
files = list_directory_files(dir)
......
......@@ -108,6 +108,7 @@ def write_build_options_header(fp):
fp.write(" output(screen,\" PIDDIR: %s\\n\", get_dyn_PIDDIR());\n")
fp.write(" output(screen,\" SMB_PASSWD_FILE: %s\\n\",get_dyn_SMB_PASSWD_FILE());\n")
fp.write(" output(screen,\" PRIVATE_DIR: %s\\n\",get_dyn_PRIVATE_DIR());\n")
fp.write(" output(screen,\" BINDDNS_DIR: %s\\n\",get_dyn_BINDDNS_DIR());\n")
fp.write("\n")
def write_build_options_footer(fp):
......
......@@ -109,6 +109,7 @@ def SAMBA_PYTHON(bld, name,
public_deps='',
realname=None,
cflags='',
cflags_end=None,
includes='',
init_function_sentinel=None,
local_include=True,
......@@ -154,6 +155,7 @@ def SAMBA_PYTHON(bld, name,
public_deps=public_deps,
includes=includes,
cflags=cflags,
cflags_end=cflags_end,
local_include=local_include,
vars=vars,
realname=realname,
......
......@@ -39,3 +39,28 @@ def CHECK_CMOCKA(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('cmocka', minversion='1.1.1')
Build.BuildContext.CHECK_CMOCKA = CHECK_CMOCKA
@conf
def CHECK_SOCKET_WRAPPER(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('socket_wrapper', minversion='1.1.9')
Build.BuildContext.CHECK_SOCKET_WRAPPER = CHECK_SOCKET_WRAPPER
@conf
def CHECK_NSS_WRAPPER(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('nss_wrapper', minversion='1.1.3')
Build.BuildContext.CHECK_NSS_WRAPPER = CHECK_NSS_WRAPPER
@conf
def CHECK_RESOLV_WRAPPER(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('resolv_wrapper', minversion='1.1.4')
Build.BuildContext.CHECK_RESOLV_WRAPPER = CHECK_RESOLV_WRAPPER
@conf
def CHECK_UID_WRAPPER(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('uid_wrapper', minversion='1.2.4')
Build.BuildContext.CHECK_UID_WRAPPER = CHECK_UID_WRAPPER
@conf
def CHECK_PAM_WRAPPER(conf):
return conf.CHECK_BUNDLED_SYSTEM_PKG('pam_wrapper', minversion='1.0.4')
Build.BuildContext.CHECK_PAM_WRAPPER = CHECK_PAM_WRAPPER
......@@ -112,6 +112,7 @@ def SAMBA_LIBRARY(bld, libname, source,
vnum=None,
soname=None,
cflags='',
cflags_end=None,
ldflags='',
external_library=False,
realname=None,
......@@ -195,6 +196,7 @@ def SAMBA_LIBRARY(bld, libname, source,
private_headers= private_headers,
header_path = header_path,
cflags = cflags,
cflags_end = cflags_end,
group = subsystem_group,
autoproto = autoproto,
autoproto_extra_source=autoproto_extra_source,
......@@ -885,13 +887,30 @@ def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
python_fixup=python_fixup, base_name=trim_path)
Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
def INSTALL_DIR(bld, path, chmod=0o755, env=None):
"""Install a directory if it doesn't exist, always set permissions."""
def INSTALL_DIRS(bld, destdir, dirs):
if not path:
return []
destpath = bld.get_install_path(path, env)
if bld.is_install > 0:
if not os.path.isdir(destpath):
try:
os.makedirs(destpath)
os.chmod(destpath, chmod)
except OSError, e:
if not os.path.isdir(destpath):
raise Utils.WafError("Cannot create the folder '%s' (error: %s)" % (path, e))
Build.BuildContext.INSTALL_DIR = INSTALL_DIR
def INSTALL_DIRS(bld, destdir, dirs, chmod=0o755, env=None):
'''install a set of directories'''
destdir = bld.EXPAND_VARIABLES(destdir)
dirs = bld.EXPAND_VARIABLES(dirs)
for d in TO_LIST(dirs):
bld.install_dir(os.path.join(destdir, d))
INSTALL_DIR(bld, os.path.join(destdir, d), chmod, env)
Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
......
......@@ -942,3 +942,8 @@ void rep_setproctitle(const char *fmt, ...)
{
}
#endif
#ifndef HAVE_SETPROCTITLE_INIT
void rep_setproctitle_init(int argc, char *argv[], char *envp[])
{
}
#endif
......@@ -918,6 +918,10 @@ int usleep(useconds_t);
void rep_setproctitle(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2);
#endif
#ifndef HAVE_SETPROCTITLE_INIT
#define setproctitle_init rep_setproctitle_init
void rep_setproctitle_init(int argc, char *argv[], char *envp[]);
#endif
bool nss_wrapper_enabled(void);
bool nss_wrapper_hosts_enabled(void);
bool socket_wrapper_enabled(void);
......
......@@ -26,6 +26,9 @@
#ifdef HAVE_LIBREADLINE
# ifdef HAVE_READLINE_READLINE_H
# ifdef HAVE_READLINE_READLINE_WORKAROUND
# define _FUNCTION_DEF
# endif
# include <readline/readline.h>
# ifdef HAVE_READLINE_HISTORY_H
# include <readline/history.h>
......
......@@ -84,6 +84,9 @@ def configure(conf):
if conf.CHECK_CFLAGS('-Wno-format-truncation'):
conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1')
if conf.CHECK_CFLAGS('-Wno-unused-function'):
conf.define('HAVE_WNO_UNUSED_FUNCTION', '1')
# Check for process set name support
conf.CHECK_CODE('''
#include <sys/prctl.h>
......@@ -249,16 +252,33 @@ def configure(conf):
if conf.CONFIG_SET('HAVE_MEMALIGN'):
conf.CHECK_DECLS('memalign', headers='malloc.h')
# glibc up to 2.3.6 had dangerously broken posix_fallocate(). DON'T USE IT.
if conf.CHECK_CODE('''
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#if defined(__GLIBC__) && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 4))
#error probably broken posix_fallocate
#endif
''',
'_POSIX_FALLOCATE_CAPABLE_LIBC',
msg='Checking for posix_fallocate-capable libc'):
conf.CHECK_FUNCS('posix_fallocate')
conf.CHECK_FUNCS('prctl dirname basename')
strlcpy_in_bsd = False
# libbsd on some platforms provides strlcpy and strlcat
if not conf.CHECK_FUNCS('strlcpy strlcat'):
conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h',
checklibc=True)
if conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h',
checklibc=True):
strlcpy_in_bsd = True
if not conf.CHECK_FUNCS('getpeereid'):
conf.CHECK_FUNCS_IN('getpeereid', 'bsd', headers='sys/types.h bsd/unistd.h')
if not conf.CHECK_FUNCS_IN('setproctitle', 'setproctitle', headers='setproctitle.h'):
conf.CHECK_FUNCS_IN('setproctitle', 'bsd', headers='sys/types.h bsd/unistd.h')
if not conf.CHECK_FUNCS('setproctitle_init'):
conf.CHECK_FUNCS_IN('setproctitle_init', 'bsd', headers='sys/types.h bsd/unistd.h')
if not conf.CHECK_FUNCS('closefrom'):
conf.CHECK_FUNCS_IN('closefrom', 'bsd', headers='bsd/unistd.h')
......@@ -611,6 +631,9 @@ removeea setea
# look for a method of finding the list of network interfaces
for method in ['HAVE_IFACE_GETIFADDRS', 'HAVE_IFACE_AIX', 'HAVE_IFACE_IFCONF', 'HAVE_IFACE_IFREQ']:
bsd_for_strlcpy = ''
if strlcpy_in_bsd:
bsd_for_strlcpy = ' bsd'
if conf.CHECK_CODE('''
#define %s 1
#define NO_CONFIG_H 1
......@@ -623,7 +646,7 @@ removeea setea
#include "test/getifaddrs.c"
''' % method,
method,
lib='nsl socket',
lib='nsl socket' + bsd_for_strlcpy,
addmain=False,
execute=True):
break
......
......@@ -75,12 +75,13 @@
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
#define TALLOC_MAGIC_BASE 0xe814ec70
static unsigned int talloc_magic = (
~TALLOC_FLAG_MASK & (
TALLOC_MAGIC_BASE +
(TALLOC_BUILD_VERSION_MAJOR << 24) +
(TALLOC_BUILD_VERSION_MINOR << 16) +
(TALLOC_BUILD_VERSION_RELEASE << 8)));
#define TALLOC_MAGIC_NON_RANDOM ( \
~TALLOC_FLAG_MASK & ( \
TALLOC_MAGIC_BASE + \
(TALLOC_BUILD_VERSION_MAJOR << 24) + \
(TALLOC_BUILD_VERSION_MINOR << 16) + \
(TALLOC_BUILD_VERSION_RELEASE << 8)))
static unsigned int talloc_magic = TALLOC_MAGIC_NON_RANDOM;
/* by default we abort when given a bad pointer (such as when talloc_free() is called
on a pointer that came from malloc() */
......@@ -332,6 +333,48 @@ _PUBLIC_ int talloc_test_get_magic(void)
return talloc_magic;
}
static inline void _talloc_chunk_set_free(struct talloc_chunk *tc,
const char *location)
{
/*
* Mark this memory as free, and also over-stamp the talloc
* magic with the old-style magic.
*
* Why? This tries to avoid a memory read use-after-free from
* disclosing our talloc magic, which would then allow an
* attacker to prepare a valid header and so run a destructor.
*
*/
tc->flags = TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE
| (tc->flags & TALLOC_FLAG_MASK);
/* 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
*/
if (location) {
tc->name = location;
}
}
static inline void _talloc_chunk_set_not_free(struct talloc_chunk *tc)
{
/*
* Mark this memory as not free.
*
* Why? This is memory either in a pool (and so available for
* talloc's re-use or after the realloc(). We need to mark
* the memory as free() before any realloc() call as we can't
* write to the memory after that.
*
* We put back the normal magic instead of the 'not random'
* magic.
*/
tc->flags = talloc_magic |
((tc->flags & TALLOC_FLAG_MASK) & ~TALLOC_FLAG_FREE);
}
static void (*talloc_log_fn)(const char *message);
_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
......@@ -429,11 +472,6 @@ static void talloc_abort(const char *reason)
talloc_abort_fn(reason);
}
static void talloc_abort_magic(unsigned magic)
{
talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
}
static void talloc_abort_access_after_free(void)
{
talloc_abort("Bad talloc magic value - access after free");
......@@ -450,19 +488,15 @@ static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
const char *pp = (const char *)ptr;
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) != talloc_magic)) {
if ((tc->flags & (~TALLOC_FLAG_MASK)) == talloc_magic) {
talloc_abort_magic(tc->flags & (~TALLOC_FLAG_MASK));
return NULL;
}
if (tc->flags & TALLOC_FLAG_FREE) {
if ((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK))
== (TALLOC_MAGIC_NON_RANDOM | TALLOC_FLAG_FREE)) {
talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
talloc_abort_access_after_free();
return NULL;
} else {
talloc_abort_unknown_value();
return NULL;
}
talloc_abort_unknown_value();
return NULL;
}
return tc;
}
......@@ -947,13 +981,7 @@ static inline void _tc_free_poolmem(struct talloc_chunk *tc,
pool_tc = talloc_chunk_from_pool(pool);
next_tc = tc_next_chunk(tc);
tc->flags |= TALLOC_FLAG_FREE;
/* 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
*/
tc->name = location;
_talloc_chunk_set_free(tc, location);
TC_INVALIDATE_FULL_CHUNK(tc);
......@@ -1103,13 +1131,7 @@ static inline int _tc_free_internal(struct talloc_chunk *tc,
_tc_free_children_internal(tc, ptr, location);
tc->flags |= TALLOC_FLAG_FREE;
/* 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
*/
tc->name = location;
_talloc_chunk_set_free(tc, location);
if (tc->flags & TALLOC_FLAG_POOL) {
struct talloc_pool_hdr *pool;
......@@ -1806,8 +1828,22 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
}
#endif
/* by resetting magic we catch users of the old memory */
tc->flags |= TALLOC_FLAG_FREE;
/*
* by resetting magic we catch users of the old memory
*
* We mark this memory as free, and also over-stamp the talloc
* magic with the old-style magic.
*
* Why? This tries to avoid a memory read use-after-free from
* disclosing our talloc magic, which would then allow an
* attacker to prepare a valid header and so run a destructor.
*
* What else? We have to re-stamp back a valid normal magic
* on this memory once realloc() is done, as it will have done
* a memcpy() into the new valid memory. We can't do this in
* reverse as that would be a real use-after-free.
*/
_talloc_chunk_set_free(tc, NULL);
#if ALWAYS_REALLOC
if (pool_hdr) {
......@@ -1906,7 +1942,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
if (new_chunk_size == old_chunk_size) {
TC_UNDEFINE_GROW_CHUNK(tc, size);
tc->flags &= ~TALLOC_FLAG_FREE;
_talloc_chunk_set_not_free(tc);
tc->size = size;
return ptr;
}
......@@ -1921,7 +1957,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
if (space_left >= space_needed) {
TC_UNDEFINE_GROW_CHUNK(tc, size);
tc->flags &= ~TALLOC_FLAG_FREE;
_talloc_chunk_set_not_free(tc);
tc->size = size;
pool_hdr->end = tc_next_chunk(tc);
return ptr;
......@@ -1951,12 +1987,24 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
got_new_ptr:
#endif
if (unlikely(!new_ptr)) {
tc->flags &= ~TALLOC_FLAG_FREE;
/*
* Ok, this is a strange spot. We have to put back
* the old talloc_magic and any flags, except the
* TALLOC_FLAG_FREE as this was not free'ed by the
* realloc() call after all
*/
_talloc_chunk_set_not_free(tc);
return NULL;
}
/*
* tc is now the new value from realloc(), the old memory we
* can't access any more and was preemptively marked as
* TALLOC_FLAG_FREE before the call. Now we mark it as not
* free again
*/
tc = (struct talloc_chunk *)new_ptr;
tc->flags &= ~TALLOC_FLAG_FREE;
_talloc_chunk_set_not_free(tc);
if (malloced) {
tc->flags &= ~TALLOC_FLAG_POOLMEM;
}
......
......@@ -2006,6 +2006,72 @@ static bool test_magic_protection(void)
return true;
}
static void test_magic_free_protection_abort(const char *reason)
{
/* exit with errcode 42 to communicate successful test to the parent process */
if (strcmp(reason, "Bad talloc magic value - access after free") == 0) {
_exit(42);
}
/* not 42 */
_exit(404);
}
static bool test_magic_free_protection(void)
{
void *pool = talloc_pool(NULL, 1024);
int *p1, *p2, *p3;
pid_t pid;
int exit_status;
printf("test: magic_free_protection\n");
p1 = talloc(pool, int);
p2 = talloc(pool, int);
/* To avoid complaints from the compiler assign values to the p1 & p2. */
*p1 = 6;
*p2 = 9;
p3 = talloc_realloc(pool, p2, int, 2048);
torture_assert("pool realloc 2048",
p3 != p2,
"failed: pointer not changed");
/*
* Now access the memory in the pool after the realloc(). It
* should be marked as free, so use of the old pointer should
* trigger the abort function
*/
pid = fork();
if (pid == 0) {
talloc_set_abort_fn(test_magic_free_protection_abort);
talloc_get_name(p2);
/* Never reached. Make compilers happy */
return true;
}
while (wait(&exit_status) != pid);
if (!WIFEXITED(exit_status)) {
printf("Child exited through unexpected abnormal means\n");
return false;
}
if (WEXITSTATUS(exit_status) != 42) {
printf("Child exited with wrong exit status\n");
return false;
}
if (WIFSIGNALED(exit_status)) {
printf("Child recieved unexpected signal\n");
return false;
}
talloc_free(pool);
printf("success: magic_free_protection\n");
return true;
}
static void test_reset(void)
{
talloc_set_log_fn(test_log_stdout);
......@@ -2092,6 +2158,8 @@ bool torture_local_talloc(struct torture_context *tctx)
ret &= test_autofree();
test_reset();
ret &= test_magic_protection();
test_reset();
ret &= test_magic_free_protection();
test_reset();
talloc_disable_null_tracking();
......
#!/usr/bin/env python
APPNAME = 'talloc'
VERSION = '2.1.10'
VERSION = '2.1.11'
blddir = 'bin'
......@@ -74,19 +74,22 @@ def configure(conf):
implied_deps='replace'):
conf.define('USING_SYSTEM_TALLOC', 1)
using_system_pytalloc_util = True
if not conf.CHECK_BUNDLED_SYSTEM_PKG('pytalloc-util', minversion=VERSION,
implied_deps='talloc replace'):
if conf.env.disable_python:
using_system_pytalloc_util = False
# We need to get a pytalloc-util for all the python versions
# we are building for
if conf.env['EXTRA_PYTHON']:
name = 'pytalloc-util' + conf.all_envs['extrapython']['PYTHON_SO_ABI_FLAG']
if not conf.CHECK_BUNDLED_SYSTEM_PKG(name, minversion=VERSION,
else:
using_system_pytalloc_util = True
if not conf.CHECK_BUNDLED_SYSTEM_PKG('pytalloc-util', minversion=VERSION,
implied_deps='talloc replace'):
using_system_pytalloc_util = False
# We need to get a pytalloc-util for all the python versions
# we are building for
if conf.env['EXTRA_PYTHON']:
name = 'pytalloc-util' + conf.all_envs['extrapython']['PYTHON_SO_ABI_FLAG']
if not conf.CHECK_BUNDLED_SYSTEM_PKG(name, minversion=VERSION,
implied_deps='talloc replace'):
using_system_pytalloc_util = False
if using_system_pytalloc_util:
conf.define('USING_SYSTEM_PYTALLOC_UTIL', 1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment