bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: undefined behavior in closeout, aggravated by libsigsegv


From: Eric Blake
Subject: Re: undefined behavior in closeout, aggravated by libsigsegv
Date: Mon, 23 Nov 2009 17:27:35 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Eric Blake <ebb9 <at> byu.net> writes:

> > How can I reproduce it?
> Meanwhile, I will try to spend some time inspecting cygwin source code to
> see if I can find another example of an internal fault that cygwin expects
> to handle, and where libsigsegv intercepting the fault can cause
> observable behavior changes, beyond just EFAULT handling.

Here's a relatively simple example.  POSIX 2001 states pthread_attr_init may 
fail with EBUSY if an object was previously initialized.  (Reliably testing 
whether an object was previously initialized turns out to be a relatively hard 
problem, so POSIX 2008 relaxed the specification by removing the 'may fail' of 
EBUSY if x is already initialized, under the cop-out that such behavior was 
already explicitly undefined, so an implementation may choose to do something 
simpler than fail with EBUSY; however, in the rationale, it still states that 
implementations are still encouraged to do an EBUSY check if feasible).

This example flushes out the libsigsegv interaction for both cygwin 1.5 and 
today's CVS cygwin 1.7.

$ cat foo.c
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sigsegv.h>

int
handler (void *addr, int bad)
{
  exit (2);
}

int main (int argc, char **argv)
{
  pthread_attr_t a;
  memset (&a, 1, sizeof a);
  pthread_attr_init (&a);

  if (1 < argc)
    sigsegv_install_handler (handler);
  pthread_attr_t b;
  memset (&b, 1, sizeof b);
  pthread_attr_init (&b);

  return 0;
}
$ gcc -o foo -Wall -g foo.c -lsigsegv
$ ./foo; echo $?
0
$ ./foo 1; echo $?
2

The way that cygwin implements EBUSY validation is by probing the contents of 
the pthread_attr_t to see if it is already initialized (that is, does the 
pointer contain the magic cookie put in place during initialization and removed 
during pthread_attr_destroy).  But since the object can be stack-allocated, and 
thus contain random bytes (simulated in the above example with the explicit 
memset to make the example more repeatable), that probe can fault.  In this 
case, a fault is a GOOD thing - it means that the object is NOT already 
initialized, so cygwin silently ignores the fault and lets pthread_attr_t 
succeed.  But if libsigsegv is compiled without --enable-EFAULT, it interferes 
with POSIX compliance.  Search for verifyable_object_isvalid in:

http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/thread.cc?
rev=1.216&content-type=text/x-cvsweb-markup&cvsroot=src

-- 
Eric Blake






reply via email to

[Prev in Thread] Current Thread [Next in Thread]