[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Fri Oct 9 21:16:03 UTC 2015
The branch, master has been updated
via 7b6d1a2 talloc: Test that talloc magic differs between processes.
via 2b9bfab talloc: Increment minor version due to added talloc_test_get_magic.
via 906a26a talloc: Provide tests access to talloc_magic
via f5135bd talloc: Test magic protection measures.
via 4a4664a lib/talloc: Provide multiple-loading detection for libtalloc via rand()
via 30ea897 lib/talloc: Disrupt buffer overflow attacks on Samba by using random magic
via 1dc0538 build: Move __attribute__ ((destructor)) and ((constructor)) tests to wafsamba
from f25a5c9 Fix a few small spelling mistakes in DEBUG messages to reduce confusion for those trying to debug stuff.
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 7b6d1a2a5d5561e641d9001901b9e43a64117681
Author: Adrian Cochrane <adrianc at catalyst.net.nz>
Date: Fri Sep 4 12:59:57 2015 +1200
talloc: Test that talloc magic differs between processes.
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Fri Oct 9 23:15:06 CEST 2015 on sn-devel-104
commit 2b9bfab36d9ae0f7fa2a989195129a1a6b62393b
Author: Adrian Cochrane <adrianc at catalyst.net.nz>
Date: Fri Oct 9 13:32:55 2015 +1300
talloc: Increment minor version due to added talloc_test_get_magic.
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 906a26a2abc70f824b654f71678314648b28d058
Author: Adrian Cochrane <adrianc at catalyst.net.nz>
Date: Fri Sep 4 12:03:33 2015 +1200
talloc: Provide tests access to talloc_magic
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit f5135bda942ff13f0baf2c629147d0755eb96090
Author: Adrian Cochrane <adrianc at catalyst.net.nz>
Date: Wed Sep 2 13:30:31 2015 +1200
talloc: Test magic protection measures.
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 4a4664a80e20544097cdd075ca5d1423e6a9b364
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Feb 24 13:43:54 2015 +1300
lib/talloc: Provide multiple-loading detection for libtalloc via rand()
The use of rand() is strongly discrouanged, but here is it ideal, as we just want to select a different
set of random bytes if we are called again within the same process.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 30ea897194c68c149d4986b22a5d964454bec258
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Oct 17 10:30:23 2013 +1300
lib/talloc: Disrupt buffer overflow attacks on Samba by using random magic
By setting the talloc magic to a random value, we make it much harder to overwrite a talloc_chunk
in a valid way with a simple buffer overflow.
The flags are placed before more senstive variables so they have to be overwritten first.
Inspired by the exploit in: http://blog.csnc.ch/wp-content/uploads/2012/07/sambaexploit_v1.0.pdf
Andrew Bartlett
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 1dc05386f20481596ee7360d6f4e628a16675d3f
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Feb 24 13:26:29 2015 +1300
build: Move __attribute__ ((destructor)) and ((constructor)) tests to wafsamba
This allows us to use them in talloc as well.
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Adrian Cochrane <adrianc at catalyst.net.nz>
Reviewed-by: Jeremy Allison <jra at samba.org>
-----------------------------------------------------------------------
Summary of changes:
buildtools/wafsamba/wscript | 34 +++++++++
...oc-util-2.0.6.sigs => pytalloc-util-2.1.4.sigs} | 0
.../ABI/{talloc-2.1.3.sigs => talloc-2.1.4.sigs} | 1 +
lib/talloc/talloc.c | 89 +++++++++++++++++-----
lib/talloc/talloc.h | 2 +
lib/talloc/test_magic_differs.sh | 14 ++++
lib/talloc/test_magic_differs_helper.c | 12 +++
lib/talloc/testsuite.c | 66 ++++++++++++++++
lib/talloc/wscript | 16 +++-
lib/uid_wrapper/wscript | 34 ---------
nsswitch/wb_common.c | 2 +-
source3/wscript | 6 --
12 files changed, 215 insertions(+), 61 deletions(-)
copy lib/talloc/ABI/{pytalloc-util-2.0.6.sigs => pytalloc-util-2.1.4.sigs} (100%)
copy lib/talloc/ABI/{talloc-2.1.3.sigs => talloc-2.1.4.sigs} (99%)
create mode 100755 lib/talloc/test_magic_differs.sh
create mode 100644 lib/talloc/test_magic_differs_helper.c
Changeset truncated at 500 lines:
diff --git a/buildtools/wafsamba/wscript b/buildtools/wafsamba/wscript
index d6bb688..422b742 100755
--- a/buildtools/wafsamba/wscript
+++ b/buildtools/wafsamba/wscript
@@ -361,6 +361,40 @@ def configure(conf):
cflags=conf.env.VISIBILITY_CFLAGS,
define='HAVE_VISIBILITY_ATTR', addmain=False)
+ # check HAVE_CONSTRUCTOR_ATTRIBUTE
+ conf.CHECK_CODE('''
+ void test_constructor_attribute(void) __attribute__ ((constructor));
+
+ void test_constructor_attribute(void)
+ {
+ return;
+ }
+
+ int main(void) {
+ return 0;
+ }
+ ''',
+ 'HAVE_CONSTRUCTOR_ATTRIBUTE',
+ addmain=False,
+ msg='Checking for library constructor support')
+
+ # check HAVE_DESTRUCTOR_ATTRIBUTE
+ conf.CHECK_CODE('''
+ void test_destructor_attribute(void) __attribute__ ((destructor));
+
+ void test_destructor_attribute(void)
+ {
+ return;
+ }
+
+ int main(void) {
+ return 0;
+ }
+ ''',
+ 'HAVE_DESTRUCTOR_ATTRIBUTE',
+ addmain=False,
+ msg='Checking for library destructor support')
+
if sys.platform.startswith('aix'):
conf.DEFINE('_ALL_SOURCE', 1, add_to_cflags=True)
# Might not be needed if ALL_SOURCE is defined
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.6.sigs b/lib/talloc/ABI/pytalloc-util-2.1.4.sigs
similarity index 100%
copy from lib/talloc/ABI/pytalloc-util-2.0.6.sigs
copy to lib/talloc/ABI/pytalloc-util-2.1.4.sigs
diff --git a/lib/talloc/ABI/talloc-2.1.3.sigs b/lib/talloc/ABI/talloc-2.1.4.sigs
similarity index 99%
copy from lib/talloc/ABI/talloc-2.1.3.sigs
copy to lib/talloc/ABI/talloc-2.1.4.sigs
index eae12cc..9969ce3 100644
--- a/lib/talloc/ABI/talloc-2.1.3.sigs
+++ b/lib/talloc/ABI/talloc-2.1.4.sigs
@@ -54,6 +54,7 @@ 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 *)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index c10fd53..90b9d96 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -33,6 +33,10 @@
#include "replace.h"
#include "talloc.h"
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#endif
+
#ifdef TALLOC_BUILD_VERSION_MAJOR
#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
@@ -60,20 +64,26 @@
#define MAX_TALLOC_SIZE 0x10000000
-#define TALLOC_MAGIC_BASE 0xe814ec70
-#define TALLOC_MAGIC ( \
- TALLOC_MAGIC_BASE + \
- (TALLOC_VERSION_MAJOR << 12) + \
- (TALLOC_VERSION_MINOR << 4) \
-)
#define TALLOC_FLAG_FREE 0x01
#define TALLOC_FLAG_LOOP 0x02
#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
+/*
+ * Bits above this are random, used to make it harder to fake talloc
+ * headers during an attack. Try not to change this without good reason.
+ */
+#define TALLOC_FLAG_MASK 0x0F
+
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+#define TALLOC_MAGIC_BASE 0xe814ec70
+static unsigned int talloc_magic = (
+ TALLOC_MAGIC_BASE +
+ (TALLOC_VERSION_MAJOR << 12) +
+ (TALLOC_VERSION_MINOR << 4));
+
/* by default we abort when given a bad pointer (such as when talloc_free() is called
on a pointer that came from malloc() */
#ifndef TALLOC_ABORT
@@ -249,13 +259,13 @@ typedef int (*talloc_destructor_t)(void *);
struct talloc_pool_hdr;
struct talloc_chunk {
+ unsigned flags;
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
struct talloc_reference_handle *refs;
talloc_destructor_t destructor;
const char *name;
size_t size;
- unsigned flags;
/*
* limit semantics:
@@ -290,6 +300,11 @@ _PUBLIC_ int talloc_version_minor(void)
return TALLOC_VERSION_MINOR;
}
+_PUBLIC_ int talloc_test_get_magic(void)
+{
+ return talloc_magic;
+}
+
static void (*talloc_log_fn)(const char *message);
_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
@@ -297,6 +312,50 @@ _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
talloc_log_fn = log_fn;
}
+#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
+void talloc_lib_init(void) __attribute__((constructor));
+void talloc_lib_init(void)
+{
+ uint32_t random_value;
+#if defined(HAVE_GETAUXVAL) && defined(AT_RANDOM)
+ uint8_t *p;
+ /*
+ * Use the kernel-provided random values used for
+ * ASLR. This won't change per-exec, which is ideal for us
+ */
+ p = (uint8_t *) getauxval(AT_RANDOM);
+ if (p) {
+ /*
+ * We get 16 bytes from getauxval. By calling rand(),
+ * a totally insecure PRNG, but one that will
+ * deterministically have a different value when called
+ * twice, we ensure that if two talloc-like libraries
+ * are somehow loaded in the same address space, that
+ * because we choose different bytes, we will keep the
+ * protection against collision of multiple talloc
+ * libs.
+ *
+ * This protection is important because the effects of
+ * passing a talloc pointer from one to the other may
+ * be very hard to determine.
+ */
+ int offset = rand() % (16 - sizeof(random_value));
+ memcpy(&random_value, p + offset, sizeof(random_value));
+ } else
+#endif
+ {
+ /*
+ * Otherwise, hope the location we are loaded in
+ * memory is randomised by someone else
+ */
+ random_value = ((uintptr_t)talloc_lib_init & 0xFFFFFFFF);
+ }
+ talloc_magic = random_value & ~TALLOC_FLAG_MASK;
+}
+#else
+#warning "No __attribute__((constructor)) support found on this platform, additional talloc security measures not available"
+#endif
+
static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
static void talloc_log(const char *fmt, ...)
{
@@ -345,12 +404,6 @@ static void talloc_abort(const char *reason)
static void talloc_abort_magic(unsigned magic)
{
- unsigned striped = magic - TALLOC_MAGIC_BASE;
- unsigned major = (striped & 0xFFFFF000) >> 12;
- unsigned minor = (striped & 0x00000FF0) >> 4;
- talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
- magic, major, minor,
- TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
}
@@ -369,9 +422,9 @@ 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 | ~0xF)) != TALLOC_MAGIC)) {
- if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
- talloc_abort_magic(tc->flags & (~0xF));
+ if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~TALLOC_FLAG_MASK)) != talloc_magic)) {
+ if ((tc->flags & (~0xF)) == talloc_magic) {
+ talloc_abort_magic(tc->flags & (~TALLOC_FLAG_MASK));
return NULL;
}
@@ -561,7 +614,7 @@ static inline struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent
pool_hdr->end = (void *)((char *)pool_hdr->end + chunk_size);
- result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
+ result->flags = talloc_magic | TALLOC_FLAG_POOLMEM;
result->pool = pool_hdr;
pool_hdr->object_count++;
@@ -617,7 +670,7 @@ static inline void *__talloc_with_prefix(const void *context, size_t size,
return NULL;
}
tc = (struct talloc_chunk *)(ptr + prefix_len);
- tc->flags = TALLOC_MAGIC;
+ tc->flags = talloc_magic;
tc->pool = NULL;
talloc_memlimit_grow(limit, total_len);
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
index 5ece54d..b7408b9 100644
--- a/lib/talloc/talloc.h
+++ b/lib/talloc/talloc.h
@@ -47,6 +47,8 @@ extern "C" {
int talloc_version_major(void);
int talloc_version_minor(void);
+/* This is mostly useful only for testing */
+int talloc_test_get_magic(void);
/**
* @brief Define a talloc parent type
diff --git a/lib/talloc/test_magic_differs.sh b/lib/talloc/test_magic_differs.sh
new file mode 100755
index 0000000..0f765f0
--- /dev/null
+++ b/lib/talloc/test_magic_differs.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# This test ensures that two different talloc processes do not use the same
+# magic value to lessen the opportunity for transferrable attacks.
+
+echo "test: magic differs"
+
+if [
+ "`./talloc_test_magic_differs_helper`" != "`./talloc_test_magic_differs_helper`"
+]; then
+ echo "failure: magic remained the same between executions"
+ exit 1
+fi
+
+echo "success: magic differs"
diff --git a/lib/talloc/test_magic_differs_helper.c b/lib/talloc/test_magic_differs_helper.c
new file mode 100644
index 0000000..6798827
--- /dev/null
+++ b/lib/talloc/test_magic_differs_helper.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include "talloc.h"
+
+/*
+ * This program is called by a testing shell script in order to ensure that
+ * if the library is loaded into different processes it uses different magic
+ * values in order to thwart security attacks.
+ */
+int main(int argc, char *argv[]) {
+ printf("%i\n", talloc_test_get_magic());
+ return 0;
+}
diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c
index c67cfb9..9f83039 100644
--- a/lib/talloc/testsuite.c
+++ b/lib/talloc/testsuite.c
@@ -31,6 +31,9 @@
#include <pthread.h>
#endif
+#include <unistd.h>
+#include <sys/wait.h>
+
#include "talloc_testsuite.h"
static struct timeval timeval_current(void)
@@ -1852,6 +1855,67 @@ static bool test_pthread_talloc_passing(void)
}
#endif
+static void test_magic_protection_abort(const char *reason)
+{
+ /* exit with errcode 42 to communicate successful test to the parent process */
+ if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
+ _exit(42);
+ } else {
+ printf("talloc aborted for an unexpected reason\n");
+ }
+}
+
+static bool test_magic_protection(void)
+{
+ void *pool = talloc_pool(NULL, 1024);
+ int *p1, *p2;
+ pid_t pid;
+ int exit_status;
+
+ printf("test: magic_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;
+
+ pid = fork();
+ if (pid == 0) {
+ talloc_set_abort_fn(test_magic_protection_abort);
+
+ /*
+ * Simulate a security attack
+ * by triggering a buffer overflow in memset to overwrite the
+ * constructor in the next pool chunk.
+ *
+ * Real attacks would attempt to set a real destructor.
+ */
+ memset(p1, '\0', 32);
+
+ /* Then the attack takes effect when the memory's freed. */
+ talloc_free(pool);
+ } else {
+ 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;
+ }
+
+ printf("success: magic_protection\n");
+ return true;
+}
+
static void test_reset(void)
{
talloc_set_log_fn(test_log_stdout);
@@ -1934,6 +1998,8 @@ bool torture_local_talloc(struct torture_context *tctx)
}
test_reset();
ret &= test_autofree();
+ test_reset();
+ ret &= test_magic_protection();
test_reset();
talloc_disable_null_tracking();
diff --git a/lib/talloc/wscript b/lib/talloc/wscript
index bbe0cb1..9cedbbf 100644
--- a/lib/talloc/wscript
+++ b/lib/talloc/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'talloc'
-VERSION = '2.1.3'
+VERSION = '2.1.4'
blddir = 'bin'
@@ -66,6 +66,9 @@ def configure(conf):
Logs.warn('Disabling pytalloc-util as python devel libs not found')
conf.env.disable_python = True
+ conf.CHECK_HEADERS('sys/auxv.h')
+ conf.CHECK_FUNCS('getauxval')
+
conf.SAMBA_CONFIG_H()
conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS()
@@ -97,6 +100,10 @@ def build(bld):
testsuite_deps,
install=False)
+ bld.SAMBA_BINARY('talloc_test_magic_differs_helper',
+ 'test_magic_differs_helper.c',
+ 'talloc', install=False)
+
else:
private_library = True
@@ -151,9 +158,14 @@ def test(ctx):
cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite')
ret = samba_utils.RUN_COMMAND(cmd)
print("testsuite returned %d" % ret)
+ magic_cmd = os.path.join(srcdir, 'lib', 'talloc',
+ 'test_magic_differs.sh')
+
+ magic_ret = samba_utils.RUN_COMMAND(magic_cmd)
+ print("magic differs test returned %d" % magic_ret)
pyret = samba_utils.RUN_PYTHON_TESTS(['test_pytalloc.py'])
print("python testsuite returned %d" % pyret)
- sys.exit(ret or pyret)
+ sys.exit(ret or magic_ret or pyret)
def dist():
'''makes a tarball for distribution'''
diff --git a/lib/uid_wrapper/wscript b/lib/uid_wrapper/wscript
index 016b33a..8e3950f 100644
--- a/lib/uid_wrapper/wscript
+++ b/lib/uid_wrapper/wscript
@@ -35,40 +35,6 @@ def configure(conf):
addmain=False,
msg='Checking for thread local storage')
- # check HAVE_CONSTRUCTOR_ATTRIBUTE
- conf.CHECK_CODE('''
- void test_constructor_attribute(void) __attribute__ ((constructor));
-
- void test_constructor_attribute(void)
- {
- return;
- }
-
- int main(void) {
- return 0;
- }
- ''',
- 'HAVE_CONSTRUCTOR_ATTRIBUTE',
- addmain=False,
- msg='Checking for library constructor support')
-
- # check HAVE_DESTRUCTOR_ATTRIBUTE
- conf.CHECK_CODE('''
- void test_destructor_attribute(void) __attribute__ ((destructor));
-
- void test_destructor_attribute(void)
- {
- return;
- }
-
- int main(void) {
- return 0;
- }
- ''',
- 'HAVE_DESTRUCTOR_ATTRIBUTE',
- addmain=False,
- msg='Checking for library destructor support')
-
if Options.options.address_sanitizer:
# check HAVE_ADDRESS_SANITIZER_ATTRIBUTE
conf.CHECK_CODE('''
diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c
index 139f010..da1a844 100644
--- a/nsswitch/wb_common.c
+++ b/nsswitch/wb_common.c
@@ -88,7 +88,7 @@ static void winbind_close_sock(struct winbindd_context *ctx)
/* Destructor for global context to ensure fd is closed */
-#if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR
+#if HAVE_DESTRUCTOR_ATTRIBUTE
__attribute__((destructor))
#endif
static void winbind_destructor(void)
diff --git a/source3/wscript b/source3/wscript
index 9ff9c20..3118f59 100644
--- a/source3/wscript
+++ b/source3/wscript
@@ -1492,12 +1492,6 @@ main() {
conf.env['CTDB_INCLUDE'] = conf.srcdir + '/ctdb/include'
conf.env.with_ctdb = True
- conf.CHECK_CODE('__attribute__((destructor)) static void cleanup(void) { }',
- 'HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR',
- addmain=False,
- link=False,
- msg='Checking whether we can compile with __attribute__((destructor))')
-
conf.CHECK_CODE('void seekdir(DIR *d, long loc) { return; }',
'SEEKDIR_RETURNS_VOID',
--
Samba Shared Repository
More information about the samba-cvs
mailing list