diff options
Diffstat (limited to 'meta-agl-bsp')
3 files changed, 72 insertions, 638 deletions
diff --git a/meta-agl-bsp/meta-core/recipes-core/glibc/files/0028-Bug-20116-Fix-use-after-free-in-pthread_create.patch b/meta-agl-bsp/meta-core/recipes-core/glibc/files/0028-Bug-20116-Fix-use-after-free-in-pthread_create.patch deleted file mode 100644 index f06f85c62..000000000 --- a/meta-agl-bsp/meta-core/recipes-core/glibc/files/0028-Bug-20116-Fix-use-after-free-in-pthread_create.patch +++ /dev/null @@ -1,637 +0,0 @@ -From e7ba24f05d86acf7072e066ea6d7b235a106688c Mon Sep 17 00:00:00 2001 -From: Carlos O'Donell <carlos@redhat.com> -Date: Sat, 28 Jan 2017 19:13:34 -0500 -Subject: [PATCH] Bug 20116: Fix use after free in pthread_create() - -The commit documents the ownership rules around 'struct pthread' and -when a thread can read or write to the descriptor. With those ownership -rules in place it becomes obvious that pd->stopped_start should not be -touched in several of the paths during thread startup, particularly so -for detached threads. In the case of detached threads, between the time -the thread is created by the OS kernel and the creating thread checks -pd->stopped_start, the detached thread might have already exited and the -memory for pd unmapped. As a regression test we add a simple test which -exercises this exact case by quickly creating detached threads with -large enough stacks to ensure the thread stack cache is bypassed and the -stacks are unmapped. Before the fix the testcase segfaults, after the -fix it works correctly and completes without issue. - -For a detailed discussion see: -https://www.sourceware.org/ml/libc-alpha/2017-01/msg00505.html - -(cherry-picked from commit f8bf15febcaf137bbec5a61101e88cd5a9d56ca8) - -Upstream-Status: Backport [master] -Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com> ---- - ChangeLog | 23 ++++ - nptl/Makefile | 3 +- - nptl/createthread.c | 10 +- - nptl/pthread_create.c | 207 +++++++++++++++++++++++++++------ - nptl/pthread_getschedparam.c | 1 + - nptl/pthread_setschedparam.c | 1 + - nptl/pthread_setschedprio.c | 1 + - nptl/tpp.c | 2 + - nptl/tst-create-detached.c | 137 ++++++++++++++++++++++ - sysdeps/nacl/createthread.c | 10 +- - sysdeps/unix/sysv/linux/createthread.c | 16 ++- - 11 files changed, 356 insertions(+), 55 deletions(-) - create mode 100644 nptl/tst-create-detached.c - -diff --git a/nptl/Makefile b/nptl/Makefile -index 0d8aadebed..7dec4edb53 100644 ---- a/nptl/Makefile -+++ b/nptl/Makefile -@@ -290,7 +290,8 @@ tests = tst-typesizes \ - tst-initializers1 $(addprefix tst-initializers1-,\ - c89 gnu89 c99 gnu99 c11 gnu11) \ - tst-bad-schedattr \ -- tst-thread_local1 tst-mutex-errorcheck tst-robust10 -+ tst-thread_local1 tst-mutex-errorcheck tst-robust10 \ -+ tst-create-detached \ - xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ - tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 - test-srcs = tst-oddstacklimit -diff --git a/nptl/createthread.c b/nptl/createthread.c -index ba2f9c7167..328f85865d 100644 ---- a/nptl/createthread.c -+++ b/nptl/createthread.c -@@ -25,16 +25,14 @@ - - static int - create_thread (struct pthread *pd, const struct pthread_attr *attr, -- bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) -+ bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) - { - /* If the implementation needs to do some tweaks to the thread after - it has been created at the OS level, it can set STOPPED_START here. */ - -- pd->stopped_start = stopped_start; -- if (__glibc_unlikely (stopped_start)) -- /* We make sure the thread does not run far by forcing it to get a -- lock. We lock it here too so that the new thread cannot continue -- until we tell it to. */ -+ pd->stopped_start = *stopped_start; -+ if (__glibc_unlikely (*stopped_start)) -+ /* See CONCURRENCY NOTES in nptl/pthread_create.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - return ENOSYS; -diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c -index a834063ad5..44b17bec86 100644 ---- a/nptl/pthread_create.c -+++ b/nptl/pthread_create.c -@@ -54,25 +54,141 @@ unsigned int __nptl_nthreads = 1; - /* Code to allocate and deallocate a stack. */ - #include "allocatestack.c" - --/* createthread.c defines this function, and two macros: -+/* CONCURRENCY NOTES: -+ -+ Understanding who is the owner of the 'struct pthread' or 'PD' -+ (refers to the value of the 'struct pthread *pd' function argument) -+ is critically important in determining exactly which operations are -+ allowed and which are not and when, particularly when it comes to the -+ implementation of pthread_create, pthread_join, pthread_detach, and -+ other functions which all operate on PD. -+ -+ The owner of PD is responsible for freeing the final resources -+ associated with PD, and may examine the memory underlying PD at any -+ point in time until it frees it back to the OS or to reuse by the -+ runtime. -+ -+ The thread which calls pthread_create is called the creating thread. -+ The creating thread begins as the owner of PD. -+ -+ During startup the new thread may examine PD in coordination with the -+ owner thread (which may be itself). -+ -+ The four cases of ownership transfer are: -+ -+ (1) Ownership of PD is released to the process (all threads may use it) -+ after the new thread starts in a joinable state -+ i.e. pthread_create returns a usable pthread_t. -+ -+ (2) Ownership of PD is released to the new thread starting in a detached -+ state. -+ -+ (3) Ownership of PD is dynamically released to a running thread via -+ pthread_detach. -+ -+ (4) Ownership of PD is acquired by the thread which calls pthread_join. -+ -+ Implementation notes: -+ -+ The PD->stopped_start and thread_ran variables are used to determine -+ exactly which of the four ownership states we are in and therefore -+ what actions can be taken. For example after (2) we cannot read or -+ write from PD anymore since the thread may no longer exist and the -+ memory may be unmapped. The most complicated cases happen during -+ thread startup: -+ -+ (a) If the created thread is in a detached (PTHREAD_CREATE_DETACHED), -+ or joinable (default PTHREAD_CREATE_JOINABLE) state and -+ STOPPED_START is true, then the creating thread has ownership of -+ PD until the PD->lock is released by pthread_create. If any -+ errors occur we are in states (c), (d), or (e) below. -+ -+ (b) If the created thread is in a detached state -+ (PTHREAD_CREATED_DETACHED), and STOPPED_START is false, then the -+ creating thread has ownership of PD until it invokes the OS -+ kernel's thread creation routine. If this routine returns -+ without error, then the created thread owns PD; otherwise, see -+ (c) and (e) below. -+ -+ (c) If the detached thread setup failed and THREAD_RAN is true, then -+ the creating thread releases ownership to the new thread by -+ sending a cancellation signal. All threads set THREAD_RAN to -+ true as quickly as possible after returning from the OS kernel's -+ thread creation routine. -+ -+ (d) If the joinable thread setup failed and THREAD_RAN is true, then -+ then the creating thread retains ownership of PD and must cleanup -+ state. Ownership cannot be released to the process via the -+ return of pthread_create since a non-zero result entails PD is -+ undefined and therefore cannot be joined to free the resources. -+ We privately call pthread_join on the thread to finish handling -+ the resource shutdown (Or at least we should, see bug 19511). -+ -+ (e) If the thread creation failed and THREAD_RAN is false, then the -+ creating thread retains ownership of PD and must cleanup state. -+ No waiting for the new thread is required because it never -+ started. -+ -+ The nptl_db interface: -+ -+ The interface with nptl_db requires that we enqueue PD into a linked -+ list and then call a function which the debugger will trap. The PD -+ will then be dequeued and control returned to the thread. The caller -+ at the time must have ownership of PD and such ownership remains -+ after control returns to thread. The enqueued PD is removed from the -+ linked list by the nptl_db callback td_thr_event_getmsg. The debugger -+ must ensure that the thread does not resume execution, otherwise -+ ownership of PD may be lost and examining PD will not be possible. -+ -+ Note that the GNU Debugger as of (December 10th 2015) commit -+ c2c2a31fdb228d41ce3db62b268efea04bd39c18 no longer uses -+ td_thr_event_getmsg and several other related nptl_db interfaces. The -+ principal reason for this is that nptl_db does not support non-stop -+ mode where other threads can run concurrently and modify runtime -+ structures currently in use by the debugger and the nptl_db -+ interface. -+ -+ Axioms: -+ -+ * The create_thread function can never set stopped_start to false. -+ * The created thread can read stopped_start but never write to it. -+ * The variable thread_ran is set some time after the OS thread -+ creation routine returns, how much time after the thread is created -+ is unspecified, but it should be as quickly as possible. -+ -+*/ -+ -+/* CREATE THREAD NOTES: -+ -+ createthread.c defines the create_thread function, and two macros: - START_THREAD_DEFN and START_THREAD_SELF (see below). - -- create_thread is obliged to initialize PD->stopped_start. It -- should be true if the STOPPED_START parameter is true, or if -- create_thread needs the new thread to synchronize at startup for -- some other implementation reason. If PD->stopped_start will be -- true, then create_thread is obliged to perform the operation -- "lll_lock (PD->lock, LLL_PRIVATE)" before starting the thread. -+ create_thread must initialize PD->stopped_start. It should be true -+ if the STOPPED_START parameter is true, or if create_thread needs the -+ new thread to synchronize at startup for some other implementation -+ reason. If STOPPED_START will be true, then create_thread is obliged -+ to lock PD->lock before starting the thread. Then pthread_create -+ unlocks PD->lock which synchronizes-with START_THREAD_DEFN in the -+ child thread which does an acquire/release of PD->lock as the last -+ action before calling the user entry point. The goal of all of this -+ is to ensure that the required initial thread attributes are applied -+ (by the creating thread) before the new thread runs user code. Note -+ that the the functions pthread_getschedparam, pthread_setschedparam, -+ pthread_setschedprio, __pthread_tpp_change_priority, and -+ __pthread_current_priority reuse the same lock, PD->lock, for a -+ similar purpose e.g. synchronizing the setting of similar thread -+ attributes. These functions are never called before the thread is -+ created, so don't participate in startup syncronization, but given -+ that the lock is present already and in the unlocked state, reusing -+ it saves space. - - The return value is zero for success or an errno code for failure. - If the return value is ENOMEM, that will be translated to EAGAIN, - so create_thread need not do that. On failure, *THREAD_RAN should - be set to true iff the thread actually started up and then got -- cancelled before calling user code (*PD->start_routine), in which -- case it is responsible for doing its own cleanup. */ -- -+ canceled before calling user code (*PD->start_routine). */ - static int create_thread (struct pthread *pd, const struct pthread_attr *attr, -- bool stopped_start, STACK_VARIABLES_PARMS, -+ bool *stopped_start, STACK_VARIABLES_PARMS, - bool *thread_ran); - - #include <createthread.c> -@@ -314,12 +430,19 @@ START_THREAD_DEFN - /* Store the new cleanup handler info. */ - THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); - -+ /* We are either in (a) or (b), and in either case we either own -+ PD already (2) or are about to own PD (1), and so our only -+ restriction would be that we can't free PD until we know we -+ have ownership (see CONCURRENCY NOTES above). */ - if (__glibc_unlikely (pd->stopped_start)) - { - int oldtype = CANCEL_ASYNC (); - - /* Get the lock the parent locked to force synchronization. */ - lll_lock (pd->lock, LLL_PRIVATE); -+ -+ /* We have ownership of PD now. */ -+ - /* And give it up right away. */ - lll_unlock (pd->lock, LLL_PRIVATE); - -@@ -378,7 +501,8 @@ START_THREAD_DEFN - pd, pd->nextevent)); - } - -- /* Now call the function to signal the event. */ -+ /* Now call the function which signals the event. See -+ CONCURRENCY NOTES for the nptl_db interface comments. */ - __nptl_death_event (); - } - } -@@ -642,19 +766,28 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, - that cares whether the thread count is correct. */ - atomic_increment (&__nptl_nthreads); - -- bool thread_ran = false; -+ /* Our local value of stopped_start and thread_ran can be accessed at -+ any time. The PD->stopped_start may only be accessed if we have -+ ownership of PD (see CONCURRENCY NOTES above). */ -+ bool stopped_start = false; bool thread_ran = false; - - /* Start the thread. */ - if (__glibc_unlikely (report_thread_creation (pd))) - { -- /* Create the thread. We always create the thread stopped -- so that it does not get far before we tell the debugger. */ -- retval = create_thread (pd, iattr, true, STACK_VARIABLES_ARGS, -- &thread_ran); -+ stopped_start = true; -+ -+ /* We always create the thread stopped at startup so we can -+ notify the debugger. */ -+ retval = create_thread (pd, iattr, &stopped_start, -+ STACK_VARIABLES_ARGS, &thread_ran); - if (retval == 0) - { -- /* create_thread should have set this so that the logic below can -- test it. */ -+ /* We retain ownership of PD until (a) (see CONCURRENCY NOTES -+ above). */ -+ -+ /* Assert stopped_start is true in both our local copy and the -+ PD copy. */ -+ assert (stopped_start); - assert (pd->stopped_start); - - /* Now fill in the information about the new thread in -@@ -671,26 +804,30 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, - pd, pd->nextevent) - != 0); - -- /* Now call the function which signals the event. */ -+ /* Now call the function which signals the event. See -+ CONCURRENCY NOTES for the nptl_db interface comments. */ - __nptl_create_event (); - } - } - else -- retval = create_thread (pd, iattr, false, STACK_VARIABLES_ARGS, -- &thread_ran); -+ retval = create_thread (pd, iattr, &stopped_start, -+ STACK_VARIABLES_ARGS, &thread_ran); - - if (__glibc_unlikely (retval != 0)) - { -- /* If thread creation "failed", that might mean that the thread got -- created and ran a little--short of running user code--but then -- create_thread cancelled it. In that case, the thread will do all -- its own cleanup just like a normal thread exit after a successful -- creation would do. */ -- - if (thread_ran) -- assert (pd->stopped_start); -+ /* State (c) or (d) and we may not have PD ownership (see -+ CONCURRENCY NOTES above). We can assert that STOPPED_START -+ must have been true because thread creation didn't fail, but -+ thread attribute setting did. */ -+ /* See bug 19511 which explains why doing nothing here is a -+ resource leak for a joinable thread. */ -+ assert (stopped_start); - else - { -+ /* State (e) and we have ownership of PD (see CONCURRENCY -+ NOTES above). */ -+ - /* Oops, we lied for a second. */ - atomic_decrement (&__nptl_nthreads); - -@@ -710,10 +847,14 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, - } - else - { -- if (pd->stopped_start) -- /* The thread blocked on this lock either because we're doing TD_CREATE -- event reporting, or for some other reason that create_thread chose. -- Now let it run free. */ -+ /* We don't know if we have PD ownership. Once we check the local -+ stopped_start we'll know if we're in state (a) or (b) (see -+ CONCURRENCY NOTES above). */ -+ if (stopped_start) -+ /* State (a), we own PD. The thread blocked on this lock either -+ because we're doing TD_CREATE event reporting, or for some -+ other reason that create_thread chose. Now let it run -+ free. */ - lll_unlock (pd->lock, LLL_PRIVATE); - - /* We now have for sure more than one thread. The main thread might -diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c -index b887881baf..de71171a08 100644 ---- a/nptl/pthread_getschedparam.c -+++ b/nptl/pthread_getschedparam.c -@@ -35,6 +35,7 @@ __pthread_getschedparam (pthread_t threadid, int *policy, - - int result = 0; - -+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - /* The library is responsible for maintaining the values at all -diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c -index dfb52b9dbf..dcb520f1c8 100644 ---- a/nptl/pthread_setschedparam.c -+++ b/nptl/pthread_setschedparam.c -@@ -36,6 +36,7 @@ __pthread_setschedparam (pthread_t threadid, int policy, - - int result = 0; - -+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - struct sched_param p; -diff --git a/nptl/pthread_setschedprio.c b/nptl/pthread_setschedprio.c -index cefc6481d6..8134b50560 100644 ---- a/nptl/pthread_setschedprio.c -+++ b/nptl/pthread_setschedprio.c -@@ -38,6 +38,7 @@ pthread_setschedprio (pthread_t threadid, int prio) - struct sched_param param; - param.sched_priority = prio; - -+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - /* If the thread should have higher priority because of some -diff --git a/nptl/tpp.c b/nptl/tpp.c -index e175bf4d53..223bd6bbee 100644 ---- a/nptl/tpp.c -+++ b/nptl/tpp.c -@@ -114,6 +114,7 @@ __pthread_tpp_change_priority (int previous_prio, int new_prio) - if (priomax == newpriomax) - return 0; - -+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ - lll_lock (self->lock, LLL_PRIVATE); - - tpp->priomax = newpriomax; -@@ -165,6 +166,7 @@ __pthread_current_priority (void) - - int result = 0; - -+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */ - lll_lock (self->lock, LLL_PRIVATE); - - if ((self->flags & ATTR_FLAG_SCHED_SET) == 0) -diff --git a/nptl/tst-create-detached.c b/nptl/tst-create-detached.c -new file mode 100644 -index 0000000000..ea93e441c7 ---- /dev/null -+++ b/nptl/tst-create-detached.c -@@ -0,0 +1,137 @@ -+/* Bug 20116: Test rapid creation of detached threads. -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; see the file COPYING.LIB. If -+ not, see <http://www.gnu.org/licenses/>. */ -+ -+/* The goal of the test is to trigger a failure if the parent touches -+ any part of the thread descriptor after the detached thread has -+ exited. We test this by creating many detached threads with large -+ stacks. The stacks quickly fill the the stack cache and subsequent -+ threads will start to cause the thread stacks to be immediately -+ unmapped to satisfy the stack cache max. With the stacks being -+ unmapped the parent's read of any part of the thread descriptor will -+ trigger a segfault. That segfault is what we are trying to cause, -+ since any segfault is a defect in the implementation. */ -+ -+#include <pthread.h> -+#include <stdio.h> -+#include <errno.h> -+#include <unistd.h> -+#include <stdbool.h> -+#include <sys/resource.h> -+#include <support/xthread.h> -+ -+/* Number of threads to create. */ -+enum { threads_to_create = 100000 }; -+ -+/* Number of threads which should spawn other threads. */ -+enum { creator_threads = 2 }; -+ -+/* Counter of threads created so far. This is incremented by all the -+ running creator threads. */ -+static unsigned threads_created; -+ -+/* Thread callback which does nothing, so that the thread exits -+ immediatedly. */ -+static void * -+do_nothing (void *arg) -+{ -+ return NULL; -+} -+ -+/* Attribute indicating that the thread should be created in a detached -+ fashion. */ -+static pthread_attr_t detached; -+ -+/* Barrier to synchronize initialization. */ -+static pthread_barrier_t barrier; -+ -+static void * -+creator_thread (void *arg) -+{ -+ int ret; -+ xpthread_barrier_wait (&barrier); -+ -+ while (true) -+ { -+ pthread_t thr; -+ /* Thread creation will fail if the kernel does not free old -+ threads quickly enough, so we do not report errors. */ -+ ret = pthread_create (&thr, &detached, do_nothing, NULL); -+ if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST) -+ >= threads_to_create) -+ break; -+ } -+ -+ return NULL; -+} -+ -+static int -+do_test (void) -+{ -+ /* Limit the size of the process, so that memory allocation will -+ fail without impacting the entire system. */ -+ { -+ struct rlimit limit; -+ if (getrlimit (RLIMIT_AS, &limit) != 0) -+ { -+ printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n"); -+ return 1; -+ } -+ /* This limit, 800MB, is just a heuristic. Any value can be -+ picked. */ -+ long target = 800 * 1024 * 1024; -+ if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target) -+ { -+ limit.rlim_cur = target; -+ if (setrlimit (RLIMIT_AS, &limit) != 0) -+ { -+ printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n"); -+ return 1; -+ } -+ } -+ } -+ -+ xpthread_attr_init (&detached); -+ -+ xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED); -+ -+ /* A large thread stack seems beneficial for reproducing a race -+ condition in detached thread creation. The goal is to reach the -+ limit of the runtime thread stack cache such that the detached -+ thread's stack is unmapped after exit and causes a segfault when -+ the parent reads the thread descriptor data stored on the the -+ unmapped stack. */ -+ xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024); -+ -+ xpthread_barrier_init (&barrier, NULL, creator_threads); -+ -+ pthread_t threads[creator_threads]; -+ -+ for (int i = 0; i < creator_threads; ++i) -+ threads[i] = xpthread_create (NULL, creator_thread, NULL); -+ -+ for (int i = 0; i < creator_threads; ++i) -+ xpthread_join (threads[i]); -+ -+ xpthread_attr_destroy (&detached); -+ -+ xpthread_barrier_destroy (&barrier); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/sysdeps/nacl/createthread.c b/sysdeps/nacl/createthread.c -index 7b571c34e2..5465558cc1 100644 ---- a/sysdeps/nacl/createthread.c -+++ b/sysdeps/nacl/createthread.c -@@ -32,15 +32,13 @@ static void start_thread (void) __attribute__ ((noreturn)); - - static int - create_thread (struct pthread *pd, const struct pthread_attr *attr, -- bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) -+ bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) - { - pd->tid = __nacl_get_tid (pd); - -- pd->stopped_start = stopped_start; -- if (__glibc_unlikely (stopped_start)) -- /* We make sure the thread does not run far by forcing it to get a -- lock. We lock it here too so that the new thread cannot continue -- until we tell it to. */ -+ pd->stopped_start = *stopped_start; -+ if (__glibc_unlikely (*stopped_start)) -+ /* See CONCURRENCY NOTES in nptl/pthread_create.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - TLS_DEFINE_INIT_TP (tp, pd); -diff --git a/sysdeps/unix/sysv/linux/createthread.c b/sysdeps/unix/sysv/linux/createthread.c -index 6d32cece48..66ddae61d4 100644 ---- a/sysdeps/unix/sysv/linux/createthread.c -+++ b/sysdeps/unix/sysv/linux/createthread.c -@@ -46,7 +46,7 @@ static int start_thread (void *arg) __attribute__ ((noreturn)); - - static int - create_thread (struct pthread *pd, const struct pthread_attr *attr, -- bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) -+ bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) - { - /* Determine whether the newly created threads has to be started - stopped since we have to set the scheduling parameters or set the -@@ -54,13 +54,11 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr, - if (attr != NULL - && (__glibc_unlikely (attr->cpuset != NULL) - || __glibc_unlikely ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0))) -- stopped_start = true; -+ *stopped_start = true; - -- pd->stopped_start = stopped_start; -- if (__glibc_unlikely (stopped_start)) -- /* We make sure the thread does not run far by forcing it to get a -- lock. We lock it here too so that the new thread cannot continue -- until we tell it to. */ -+ pd->stopped_start = *stopped_start; -+ if (__glibc_unlikely (*stopped_start)) -+ /* See CONCURRENCY NOTES in nptl/pthread_creat.c. */ - lll_lock (pd->lock, LLL_PRIVATE); - - /* We rely heavily on various flags the CLONE function understands: -@@ -117,7 +115,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr, - /* Set the affinity mask if necessary. */ - if (attr->cpuset != NULL) - { -- assert (stopped_start); -+ assert (*stopped_start); - - res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, - attr->cpusetsize, attr->cpuset); -@@ -140,7 +138,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr, - /* Set the scheduling parameters. */ - if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) - { -- assert (stopped_start); -+ assert (*stopped_start); - - res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, - pd->schedpolicy, &pd->schedparam); --- -2.11.0 - diff --git a/meta-agl-bsp/meta-core/recipes-core/glibc/files/CVE-2017-1000366.backport.patch b/meta-agl-bsp/meta-core/recipes-core/glibc/files/CVE-2017-1000366.backport.patch new file mode 100644 index 000000000..8ce5ca2bc --- /dev/null +++ b/meta-agl-bsp/meta-core/recipes-core/glibc/files/CVE-2017-1000366.backport.patch @@ -0,0 +1,71 @@ +# Source: https://sourceware.org/git/?p=glibc.git;a=patch;h=87bd4186da10371f46e2f1a7bf7c0a45bb04f1ac +# Modified: removed Changelog and NEWS from patch to apply across multiple revisions +# Upstream status: backport +# +# 2017-09-05 jsmoeller@linuxfoundation.org + +From 87bd4186da10371f46e2f1a7bf7c0a45bb04f1ac Mon Sep 17 00:00:00 2001 +From: Florian Weimer <fweimer@redhat.com> +Date: Mon, 19 Jun 2017 18:33:26 +0200 +Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1 + programs [BZ #21624] + +LD_LIBRARY_PATH can only be used to reorder system search paths, which +is not useful functionality. + +This makes an exploitable unbounded alloca in _dl_init_paths unreachable +for AT_SECURE=1 programs. + +(cherry picked from commit f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d) +--- + ChangeLog | 7 +++++++ + NEWS | 1 + + elf/rtld.c | 3 ++- + 3 files changed, 10 insertions(+), 1 deletion(-) + +# removed to apply on older version ... +# +#diff --git a/ChangeLog b/ChangeLog +#index 1795e28..e37f14f 100644 +#--- a/ChangeLog +#+++ b/ChangeLog +#@@ -1,3 +1,10 @@ +#+2017-06-19 Florian Weimer <fweimer@redhat.com> +#+ +#+ [BZ #21624] +#+ CVE-2017-1000366 +#+ * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for +#+ __libc_enable_secure. +#+ +# 2017-02-01 Andreas Schwab <schwab@linux-m68k.org> +# +# * sysdeps/m68k/m680x0/m68020/atomic-machine.h +#diff --git a/NEWS b/NEWS +#index 82a718f..d42af91 100644 +#--- a/NEWS +#+++ b/NEWS +#@@ -25,6 +25,7 @@ The following bugs are resolved with this release: +# +# [21289] Fix symbol redirect for fts_set +# [21386] Assertion in fork for distinct parent PID is incorrect +#+ [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366) +# +# Version 2.24 +# +diff --git a/elf/rtld.c b/elf/rtld.c +index 647661c..215a9ae 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2437,7 +2437,8 @@ process_envvars (enum mode *modep) + + case 12: + /* The library search path. */ +- if (memcmp (envline, "LIBRARY_PATH", 12) == 0) ++ if (!__libc_enable_secure ++ && memcmp (envline, "LIBRARY_PATH", 12) == 0) + { + library_path = &envline[13]; + break; +-- +2.9.3 + diff --git a/meta-agl-bsp/meta-core/recipes-core/glibc/glibc_2.24.bbappend b/meta-agl-bsp/meta-core/recipes-core/glibc/glibc_2.24.bbappend index a9f2a238d..99786fb19 100644 --- a/meta-agl-bsp/meta-core/recipes-core/glibc/glibc_2.24.bbappend +++ b/meta-agl-bsp/meta-core/recipes-core/glibc/glibc_2.24.bbappend @@ -1,4 +1,4 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" # include fix for CVE-2017-1000366 -SRCREV = "86ac4a78a9218d1e1dcfbacc6f7d09957c1fe3a4"
\ No newline at end of file +SRC_URI_append = " file://CVE-2017-1000366.backport.patch"
\ No newline at end of file |