Bug 1290432

Summary: PCRE-JITted code should be executed from non-writable memory to obey execmem SELinux restriction
Product: Red Hat Enterprise Linux 7 Reporter: Petr Lautrbach <plautrba>
Component: pcreAssignee: Petr Pisar <ppisar>
Status: CLOSED CANTFIX QA Contact: BaseOS QE - Apps <qe-baseos-apps>
Severity: medium Docs Contact: Vladimír Slávik <vslavik>
Priority: medium    
Version: 7.2CC: carl, jkejda, mgrepl, mjahoda, phracek, plautrba, ppisar, qe-baseos-daemons, rcollet, ssekidde
Target Milestone: rcKeywords: FutureFeature
Target Release: ---   
Hardware: x86_64   
OS: Linux   
URL: https://bugs.exim.org/show_bug.cgi?id=1749
Whiteboard:
Fixed In Version: Doc Type: Known Issue
Doc Text:
Performance of regular expressions cannot be boosted with the JIT technique if executable stack is disabled When the *SELinux* policy disallows executable stack, the *PCRE* library cannot use JIT compilation to speed up regular expressions. As a result, attempting JIT compilation for regular expressions is ignored and their performance is not boosted. To work around this problem, amend the *SELinux* policy with a rule for enabling the "execmem" action on affected *SELinux* domains to enable JIT compilation. Some of the rules are already provided and can be enabled by specific SELinux booleans. To list these booleans, see the output of the following command: getsebool -a | grep execmem An alternative workaround is changing application code to not request JIT compilation with calls to the *pcre_study()* function.
Story Points: ---
Clone Of: 1290205 Environment:
Last Closed: 2018-03-02 14:48:02 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1298243, 1420851    

Description Petr Lautrbach 2015-12-10 13:55:48 UTC
+++ This bug was initially created as a clone of Bug #1290205 +++

Description of problem:

When rear is being executed, e.g. /usr/sbin/rear mkrescue an SELinux AVC is generated. 

type=AVC msg=audit(1448377615.693:35710): avc:  denied  { execmem } for  pid=21398 comm="grep" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process

type=SYSCALL msg=audit(1448377615.693:35710): arch=x86_64 syscall=mmap success=no exit=EACCES a0=0 a1=10000 a2=7 a3=22 items=0 ppid=9928 pid=21398 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm=grep exe=/usr/bin/grep subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)

SELinux is preventing /usr/bin/grep from using the execmem access on a process. The root cause seems to be the usage of "grep -P".


The problem is in sljit/sljitExecAllocator.c:

 97 static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
 98 {
 99         void* retval;
100 
101 #ifdef MAP_ANON
102         retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
103 #else
104         if (dev_zero < 0) {
105                 if (open_dev_zero())
106                         return NULL;
107         }
108         retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
109 #endif
110 
111         return (retval != MAP_FAILED) ? retval : NULL;
112 }

where it tries to map anonymous memory with PROT_WRITE and PROT_EXEC. Would it be possible to change this according to Ulrich Drepper's suggestion [1] ?

[1] http://www.akkadia.org/drepper/selinux-mem.html

Comment 1 Petr Pisar 2015-12-10 14:38:45 UTC
pcre-8.32-15.el7 is affected.

Comment 3 Petr Pisar 2015-12-10 15:16:57 UTC
Enhancement request forwarded to PCRE upstream <https://bugs.exim.org/show_bug.cgi?id=1749>.

Comment 7 Remi Collet 2016-11-25 07:57:51 UTC
Notice: this may also affects rh-php70 SCL when pcre.jit=1 (but default value is 0)

Comment 8 Petr Pisar 2017-01-12 14:59:28 UTC
Upstream is working on the double mapping technique (currently x86, x86_64 and aarch64 JIT compilers work). But the technique has a drawback of a need for temporary files. If a process is not allowed to create them, the JIT compilation will fail. Therefore PCRE applications are still will be advised to cope with unavailable JIT at run time.

Comment 17 Petr Pisar 2018-03-02 14:48:02 UTC
We tried hard together with PCRE authors to bring a reliable solution. However it turned there are corner cases where it does not work (multi-threaded applications calling fork()).

At the end any solution would actually break the security hardening: If a policy disallows modifying an executable memory, then it's on a purpose. Just-in-time compilation is intrinsically incompatible with this restriction and the tested imperfect implementation only relied on imperfect policy enforcement in the Linux kernel.

Therefore we officially decline this request for enhancing pcre package. This resolution applies to pcre as well as to pcre2 software.

Users who want to benefit from a JIT have to enable execmem action on affected SELinux domains (or stop enforcing noexecmem global policy). If users are missing such knob in existing SELinux policy (getsebool -a | grep execmem), they should report a future request against the affected program or against selinux-policy Bugzilla component.