Bug 2142791
| Summary: | AVC on mmap() when executing "grep -P" and deny_execmem boolean is enabled | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux 8 | Reporter: | Renaud Métrich <rmetrich> |
| Component: | selinux-policy | Assignee: | Zdenek Pytela <zpytela> |
| Status: | CLOSED MIGRATED | QA Contact: | Milos Malik <mmalik> |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | 8.7 | CC: | ljavorsk, lvrabec, mmalik, nknazeko, plautrba, ppaddhar, ppisar, zpytela |
| Target Milestone: | rc | Keywords: | MigratedToJIRA, Reopened, Triaged |
| Target Release: | --- | Flags: | pm-rhel:
mirror+
|
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | If docs needed, set a value | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2023-09-02 01:00:05 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: | |||
Adding PCRE maintainers as well since they should be aware of the issue. The assessment is correct. If an application (grep) requests a JIT compilation, PCRE tries to mmap() the memory, it fails and falls back to an interpreted regexp matching. A collateral damage is the AVC warning. A general approach is patching SELinux policy for the given application to hide the warning. A disadvantage is one need to do this for each SELinux domain. One could hide the warnings globally, but that would hide all breach attempts utilizing this attack vector. Theoretically, PCRE library could be enhanced to check the deny_execmem SELinux boolean before calling mmap(). That would prevent from logging the warning at one place. However, I'm not sure it's the best (security, performance) approach. Can SELinux maintainers comment on it? It's also necessary to highlight that PCRE library is in no-new-features maintenance mode. If this approach proved fruitful, it would aim PCRE2 library (which is not used by RHEL 8 grep). (In reply to Petr Pisar from comment #2) > Theoretically, PCRE library could be enhanced to check the deny_execmem > SELinux boolean before calling mmap(). That would prevent from logging the > warning at one place. However, I'm not sure it's the best (security, > performance) approach. Can SELinux maintainers comment on it? It's also > necessary to highlight that PCRE library is in no-new-features maintenance > mode. If this approach proved fruitful, it would aim PCRE2 library (which is > not used by RHEL 8 grep). It might be a solution just for RHEL selinux-policy where `deny_execmem` boolean is defined. A general SELinux policy doesn't necessarily define that and it's not even defined in refpolicy - the original upstream for RHEL policy. From my POV, it seems to be something what could be only solved by a user. If they enable `deny_execmen` they most likely want to know when this happens and if it's something expected, as in this particular case, they could add their own 'dontaudit' local policy. I understand nothing can be done on the PCRE library for now, also, if a user enables `deny_execmem`, he has to deal with AVCs that will pop up. Unfortunately the solution with adding dontaudit rules is not that simple, because the user just cannot know if the AVC is legit or not, since the granularity of AVCs is on SELinux types only and it's not possible to specify to which executable it should apply. Hence to enhance the granularity, the user would have to create a specific type for *grep* (e.g. `grep_exec_t`), then add some transition which would then allow allowing execmem for grep only, whatever the caller context is. I reviewed this bz and haven't managed to find any other solution or a different approach towards resolving the reported issue. I deny_execmem is enabled, the related permissions are denied and audited. I think this is the correct and expected behaviour. It is then up to the administrator to assess the denials and decide upon further actions. If no other concern appears here, I will close the bz. FYI refpolicy has: gen_tunable(allow_execmem,false) I disagree with this: it's not possible for the administrator to analyze such denies and whitelist those based on some rule (e.g. "execution of grep is allowed") because the program can potentially run in any context since "grep" doesn't execute in its own context. As no new information appeared during the past weeks, we are going to close this bug. If you need to pursue this matter forward, feel free to reopen this bug and attach the information needed for further assessing. Issue migration from Bugzilla to Jira is in process at this time. This will be the last message in Jira copied from the Bugzilla bug. This BZ has been automatically migrated to the issues.redhat.com Red Hat Issue Tracker. All future work related to this report will be managed there. Due to differences in account names between systems, some fields were not replicated. Be sure to add yourself to Jira issue's "Watchers" field to continue receiving updates and add others to the "Need Info From" field to continue requesting information. To find the migrated issue, look in the "Links" section for a direct link to the new issue location. The issue key will have an icon of 2 footprints next to it, and begin with "RHEL-" followed by an integer. You can also find this issue by visiting https://issues.redhat.com/issues/?jql= and searching the "Bugzilla Bug" field for this BZ's number, e.g. a search like: "Bugzilla Bug" = 1234567 In the event you have trouble locating or viewing this issue, you can file an issue by sending mail to rh-issues. |
Description of problem: When SELinux boolean "deny_execmem" is enabled (which is not the default), any execution of "grep -P" leads to getting an AVC, as shown in the example below: -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- # grep -P -o '^BOOT_IMAGE=(\S+)' /proc/cmdline # ausearch -m avc -i -ts recent ... type=PROCTITLE msg=audit(11/15/2022 10:26:05.953:257) : proctitle=grep --color=auto -P -o ^BOOT_IMAGE=(\S+) /proc/cmdline type=SYSCALL msg=audit(11/15/2022 10:26:05.953:257) : arch=x86_64 syscall=mmap success=no exit=EACCES(Permission denied) a0=0x0 a1=0x10000 a2=PROT_READ|PROT_WRITE|PROT_EXEC a3=MAP_PRIVATE|MAP_ANONYMOUS items=0 ppid=12956 pid=15740 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts1 ses=3 comm=grep exe=/usr/bin/grep subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) type=AVC msg=audit(11/15/2022 10:26:05.953:257) : avc: denied { execmem } for pid=15740 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 permissive=0 -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- The root cause for this is "grep" internally calling libpcre's code which tries to execute code in memory: -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- (gdb) bt #0 0x00007f1db63a4af7 in mmap64 () from /lib64/libc.so.6 #1 0x00007f1db6670370 in alloc_chunk (size=65536) at sljit/sljitExecAllocator.c:213 #2 sljit_malloc_exec (size=936) at sljit/sljitExecAllocator.c:213 #3 sljit_generate_code (compiler=compiler@entry=0x559c95857ef0) at sljit/sljitNativeX86_common.c:506 #4 0x00007f1db668ce9a in _pcre_jit_compile (re=re@entry=0x559c95857d30, extra=extra@entry=0x559c95857da0, mode=mode@entry=0) at pcre_jit_compile.c:11522 #5 0x00007f1db6690742 in pcre_study (external_re=0x559c95857d30, options=options@entry=1, errorptr=errorptr@entry=0x7ffdd9551168) at pcre_study.c:1630 #6 0x0000559c945fdb9d in Pcompile (pattern=0x559c958577a0 "^BOOT_IMAGE=(\\S+)", size=<optimized out>, ignored=<optimized out>) at pcresearch.c:161 #7 0x0000559c945f6bc5 in main (argc=6, argv=0x7ffdd9551938) at grep.c:2884 -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- IMHO when "deny_execmem" is enabled, mmap AVCs, which are expected, should be hidden. It's then up to the caller to take appropriate action (here libpcre doesn't fail but uses another way, from my understanding). Since troubleshooting may be more difficult due to hiding the AVC, having a boolean to unhide those may be a good option, something like "dontaudit_mmap" or similar. It should be "on" by default. Version-Release number of selected component (if applicable): grep-3.1-6.el8.x86_64 selinux-policy-3.14.3-108.el8.noarch pcre-8.42-6.el8.x86_64 How reproducible: Always Steps to Reproduce: 1. Enable "deny_execmem" boolean # semanage boolean -m --on deny_execmem 2. Execute "grep -P" command # grep -P -o '^BOOT_IMAGE=(\S+)' /proc/cmdline Actual results: AVC but grep functional Expected results: No AVC Additional info: "grep -P" is used in kexec-tools-2.0.24-6.el8 but can be used in any other script.