Bug 17561 - GLIBC 2.20 results in SIGILL on x86_64 with double pthread_rwlock_unlock()
Summary: GLIBC 2.20 results in SIGILL on x86_64 with double pthread_rwlock_unlock()
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: nptl (show other bugs)
Version: 2.20
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-06 19:57 UTC by Aaro Koskinen
Modified: 2017-12-12 10:29 UTC (History)
4 users (show)

See Also:
Host: x86_64-linux-gnu
Target: x86_64-linux-gnu
Build: x86_64-linux-gnu
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aaro Koskinen 2014-11-06 19:57:19 UTC
The following program fails with illegal instruction on x86_64 on HW where _xend() is not supported (even if it would the behaviour is not probably correct):

$ cat foo.c
#include <pthread.h>
#include <stdio.h>

int main(void)
{
        pthread_rwlock_t _lock;

        pthread_rwlock_init(&_lock, 0);
        pthread_rwlock_wrlock(&_lock);
        pthread_rwlock_unlock(&_lock);
        pthread_rwlock_unlock(&_lock);
        pthread_rwlock_destroy(&_lock);
        return 0;
}
$ gcc foo.c -lpthread
$ ./a.out
Illegal instruction

This is caused by __pthread_rwlock_unlock() -> ELIDE_UNLOCK() -> _xend()
Comment 1 Florian Weimer 2014-11-06 20:54:03 UTC
This test case is invalid.  Calling pthread_rwlock_unlock on an rwlock which is not locked is undefined.
Comment 2 Aaro Koskinen 2014-11-06 21:02:58 UTC
Ok, such programs can be considered broken.

I was also pointed a workaround if you still need to run such:
https://github.com/andikleen/tsx-tools/blob/master/ignore-xend.c
Comment 3 Andi Kleen 2014-11-07 00:41:20 UTC
Yes don't do that as it's undefined.

In theory it would be possible to put a workaround into glibc for it, but it would make the unlock path slower and so far it was not deemed needed for this undefined case.
Comment 4 Andrey Zabolotnyi 2017-12-12 10:05:07 UTC
Manual page for pthread_rwlock_unlock says:

[...]If an implementation detects that the value specified  by  the  rwlock  argument  to  pthread_rwlock_unlock() refers  to a read-write lock object for which the current thread does not hold a lock, it is recommended that the function should fail and report an [EPERM] error.

So at least the current implementation does not follow the standard recommendation.

Same applies for pthread_rwlock_rdlock() and then twice calling pthread_rwlock_unlock() - program will SIGSEGV (in my case).
Comment 5 Andreas Schwab 2017-12-12 10:29:32 UTC
It does follow, by not trying to detect the undefined situation.