strerror() not thread-safe -- does it matter?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

strerror() not thread-safe -- does it matter?

Josh Haberman
Lua uses strerror() in several places (lauxlib.c, liolib.c, luac.c),
but it is not thread-safe.  On my system (OS X) strerror's static
buffer is initialized to all-NULL, and therefore guaranteed to be
NULL-terminated (even with racing writes), but are there systems where
a race could crash the program?  An extremely low chance of an
incorrect/garbled message seems acceptable, but the potential for a
crash (or even a security exploit) seems bad.

Has this come up before?

Josh

Reply | Threaded
Open this post in threaded view
|

Re: strerror() not thread-safe -- does it matter?

William Ahern
On Fri, Mar 23, 2012 at 01:32:18AM -0700, Josh Haberman wrote:

> Lua uses strerror() in several places (lauxlib.c, liolib.c, luac.c),
> but it is not thread-safe.  On my system (OS X) strerror's static
> buffer is initialized to all-NULL, and therefore guaranteed to be
> NULL-terminated (even with racing writes), but are there systems where
> a race could crash the program?  An extremely low chance of an
> incorrect/garbled message seems acceptable, but the potential for a
> crash (or even a security exploit) seems bad.
>
> Has this come up before?
>

There's no easy way around this. The C standard doesn't provide a
thread-safe version of strerror, not even the new C11 standard which
provides threading. See section 7.23.6.2 of C11.

IMO, this is mostly  a quality of implementation issue. Any implementation
worth its salt should either return static, constant strings (at least for
the known errnos), or use thread-local-storage for its buffers.

That said, with the POSIX flag perhaps Lua could use strerror_r(). C11 Annex
K has strerror_s, but only Microsoft supports Annex K, and only partially at
that even though they sponsored it.


Reply | Threaded
Open this post in threaded view
|

Re: strerror() not thread-safe -- does it matter?

Florian Weimer
* William Ahern:

> That said, with the POSIX flag perhaps Lua could use strerror_r().

Unfortunately, there are two incompatible implementations of
strerror_r which appear to be equally wide-spread.

Reply | Threaded
Open this post in threaded view
|

Re: strerror() not thread-safe -- does it matter?

Josh Haberman
In reply to this post by William Ahern
On Fri, Mar 23, 2012 at 2:20 AM, William Ahern
<[hidden email]> wrote:
> There's no easy way around this. The C standard doesn't provide a
> thread-safe version of strerror, not even the new C11 standard which
> provides threading. See section 7.23.6.2 of C11.

Yes, that was my conundrum (I'm facing the same question in my own
library, which is why I asked).  There's no easy way around it, but if
using strerror() were actively dangerous then the only safe choice
would be not to use it at all.  It would be unfortunate to give up
this functionality.

Basically I was hoping someone would say something like "I've looked
into this, and no modern platform will ever crash due to strerror
races."  :)

> IMO, this is mostly  a quality of implementation issue. Any implementation
> worth its salt should either return static, constant strings (at least for
> the known errnos), or use thread-local-storage for its buffers.

Apple's libc doesn't:
http://opensource.apple.com/source/Libc/Libc-763.12/string/strerror-fbsd.c

And the following program aborts rapidly (0-150 iterations) on OS X
(but not Linux):

#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>

void loop(int num) {
  char expected[80];
  int count = 0;
  strerror_r(num, expected, sizeof(expected));
  while (1) {
    if (strcmp(expected, strerror(num))) {
      fprintf(stderr, "Failed after %d interations\n", count);
      abort();
    }
    count++;
  }
}

void *thread(void *arg) { loop(1); }

int main() {
  pthread_t th;
  pthread_create(&th, NULL, &thread, NULL);
  loop(2);
  return 0;
}

Josh