libselinux: fix thread safety issues with lookup_common()

There are two problems with lookup_common() and therefore
selabel_lookup() and related functions that this patch fixes:

1) A race with the lazy compilation of regexes.  Since the struct
regex_data is allocated and assigned immediately to the parent struct
spec, it's possible for a second thread to see that this pointer is
non-NULL before the regex compilation has finished.  This typically
results in a -1 return from selabel_lookup() with ENOENT as errno.

This is fixed by adding synchronization in compile_regex().

2) A race with PCRE2 regex_match().  A struct pcre2_match_data is
created once and used for all regex matches for a given regex.  This
is problematic if two threads are attempting to evaluate the same
regex simultaneously.  This typically results in a successful return
from selabel_lookup() but with an erroneous selabel.

This is fixed by adding a pthread_mutex within regex_match() for
PCRE2.  Note, on my system, creating new matchdata takes roughly an
order of magnitude more time than locking a non-contended
pthread_mutex.  I don't believe programs will have enough contention
on this lock to justify that cost.

Bug: 63861738
Test: ueventd unit tests
Change-Id: I13bf782d81d0a0b896d444e396f307ad0dbacb6a
5 files changed