On Fri, Dec 16 2022, Mathias Krause wrote: > From: Carlo Marcelo Arenas Belón <carenas@xxxxxxxxx> > > Under Linux systems with SELinux's 'deny_execmem' or PaX's MPROTECT > enabled, the allocation of PCRE2's JIT rwx memory may be prohibited, > making pcre2_jit_compile() fail with PCRE2_ERROR_NOMEMORY (-48): > > [user@fedora git]$ git grep -c PCRE2_JIT > grep.c:1 > > [user@fedora git]$ # Enable SELinux's W^X policy > [user@fedora git]$ sudo semanage boolean -m -1 deny_execmem > > [user@fedora git]$ # JIT memory allocation fails, breaking 'git grep' > [user@fedora git]$ git grep -c PCRE2_JIT > fatal: Couldn't JIT the PCRE2 pattern 'PCRE2_JIT', got '-48' > > Instead of failing hard in this case and making 'git grep' unusable on > such systems, simply fall back to interpreter mode, leading to a much > better user experience. > > Such a change was already proposed 4 years ago [1] but wasn't merged for > unknown reasons. Yeah, it's unfortunate that it fell between the cracks, and it's good to have such a fallback mechanism. > 1. https://lore.kernel.org/r/20181209230024.43444-3-carenas@xxxxxxxxx > > Signed-off-by: Carlo Marcelo Arenas Belón <carenas@xxxxxxxxx> > Signed-off-by: Mathias Krause <minipli@xxxxxxxxxxxxxx> # tweaked changelog, added comment > --- > grep.c | 17 +++++++++++++++-- > 1 file changed, 15 insertions(+), 2 deletions(-) > > diff --git a/grep.c b/grep.c > index 06eed694936c..f2ada528b21d 100644 > --- a/grep.c > +++ b/grep.c > @@ -317,8 +317,21 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt > pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on); > if (p->pcre2_jit_on) { > jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE); > - if (jitret) > - die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret); > + if (jitret) { > + /* > + * Even though pcre2_config(PCRE2_CONFIG_JIT, ...) > + * indicated JIT support, the library might still > + * fail to generate JIT code for various reasons, > + * e.g. when SELinux's 'deny_execmem' or PaX's > + * MPROTECT prevent creating W|X memory mappings. > + * > + * Instead of faling hard, fall back to interpreter > + * mode, just as if the pattern was prefixed with > + * '(*NO_JIT)'. > + */ > + p->pcre2_jit_on = 0; > + return; >From my reading of the docs it returns two different codes: PCRE2_ERROR_JIT_BADOPTION or PCRE2_ERROR_NOMEMORY. This change will start treating both the same, but we only want to allow the latter, surely? So shouldn't this be e.g.: jitret = pcre2_jit_compile(...); if (jitret == PCRE2_ERROR_NOMEMORY) { /* code you added here */ } else if (jitret) { BUG(...); } I put a BUG() there, we could keep the die(), but PCRE2_ERROR_JIT_BADOPTION is really more appropriate as a BUG(), and if it starts returning any other codes our use of the API is also in some unknown state, so we should also BUG() out.