X-Spam-Check-By: sourceware.org From: Jonathan Lennox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BbD1p5SQYv" Content-Transfer-Encoding: 7bit Message-ID: <17433.39495.950903.287320@metro-north.cs.columbia.edu> Date: Thu, 16 Mar 2006 12:03:03 -0500 To: cygwin AT cygwin DOT com Subject: pthread_create leaves valid mutex pointers on the stack Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --BbD1p5SQYv Content-Type: text/plain; charset=us-ascii Content-Description: message body text Content-Transfer-Encoding: 7bit Cygwin's pthread_create function leaves a pointer to the pthread object's mutex member on the stack. If you subsequently call pthread_mutex_init on mutex in an automatic variable, it's possible for it to reuse this stack slot. In this case, pthread_mutex_init observes that the mutex object is a pointer to a valid mutex object, and fails with EBUSY. This program illustrates the problem, with cygwin 1.5.19-4 and gcc 3.4.4-1: --BbD1p5SQYv Content-Type: text/plain Content-Disposition: inline; filename="PthreadStackMutex.c" Content-Transfer-Encoding: 7bit #include #include #include #include #include /* expr is an expression returning 0 on success, or an errno value * on failure. */ #define Pth(expr) \ do { \ int ret; \ if ((ret = (expr)) != 0) { \ errno = ret; \ perror(#expr); \ exit(1); \ } \ } while (0) void* thread_function(void* arg) { sleep(1); return NULL; } #define STACK_ADJUST 74 void stack_function(void) { long adjust[STACK_ADJUST] __attribute__((__unused__)); pthread_mutex_t mutex[4]; Pth (pthread_mutex_init(&mutex[0], NULL)); Pth (pthread_mutex_lock(&mutex[0])); Pth (pthread_mutex_unlock(&mutex[0])); Pth (pthread_mutex_destroy(&mutex[0])); } int main() { pthread_t thread; void *thread_ret; Pth (pthread_create(&thread, NULL, &thread_function, NULL)); stack_function(); Pth (pthread_join(thread, &thread_ret)); return 0; } --BbD1p5SQYv Content-Type: text/plain; charset=us-ascii Content-Description: message body and .signature Content-Transfer-Encoding: 7bit In general, the idea of verifying objects on their init functions seems dubious to me -- how can you tell initialized objects from random stack or heap garbage? In particular, it seems like this is an area where an attacker could potentially cause odd effects by causing the pthread objects' magic numbers to be written to the stack or heap in memory that is subsequently re-used. -- Jonathan Lennox lennox at cs dot columbia dot edu --BbD1p5SQYv Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --BbD1p5SQYv--