nginx with SELinux and ngx_http_lua_module – PANIC: unprotected error in call to Lua API

main menu
runtime code generation failed restricted kernel

The CentOS 8 (CentOS Stream 9, too) might prevent to successfully execute a Lua code in NGINX web server with the modules like ngx_http_lua_module because of insufficient SELinux rules. By default, the web server is not allowed to execute programs that require memory addresses that are both executable and writable. Using Lua code may even crash with a core dump and restart of the NGIX worker process. The error logs contains information for the incident:

PANIC: unprotected error in call to Lua API (runtime code generation failed, restricted kernel?)

In fact, the error message hints what is going on – that the kernel prevents the execution of a code, which might be an addition limit enforced to this system.
Searching through the SELinux audit log shows the solution by enable the httpd_execmem SELinux boolean.

[root@srv ]# ausearch -c 'nginx' --raw | audit2allow

#============= httpd_t ==============

#!!!! This avc can be allowed using the boolean 'httpd_execmem'
allow httpd_t self:process execmem;

Apparently, the Lua code used needs a privileges to execute a code in the memory addresses (execmem). So when using the OpenResty ngx_http_lua_module, which is not distributed with the NGINX server, the server administrator should enable to true the SELinux boolean – httpd_execmem with:

setsebool -P httpd_execmem=1

The “-P” is going to make the value persistent over reboots.

Note, the official manual for the SELinux boolean. By enabling the httpd_execmem, several SELinux rules are applied, which may make the web server less secure, because the web server process is allowed to execute code in the memory.

– httpd_execmem

When enabled, this Boolean allows httpd to execute programs that require memory addresses that are both executable and writable. Enabling this Boolean is not recommended from a security standpoint as it reduces protection against buffer overflows, however certain modules and applications (such as Java and Mono applications) require this privilege.

The AVC (Access Vector Cache) message looks like:

type=AVC msg=audit(1699774004.724:59165857): avc:  denied  { execmem } for  pid=3872876 comm="nginx" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=process permissive=0
type=SYSCALL msg=audit(1699774004.724:59165857): arch=c000003e syscall=10 success=no exit=-13 a0=7f399cd69000 a1=10000 a2=5 a3=38 items=0 ppid=884311 pid=3872876 auid=4294967295 uid=990 gid=987 euid=990 suid=990 fsuid=990 egid=987 sgid=987 fsgid=987 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=mprotect AUID="unset" UID="nginx" GID="nginx" EUID="nginx" SUID="nginx" FSUID="nginx" EGID="nginx" SGID="nginx" FSGID="nginx"
type=PROCTITLE msg=audit(1699774004.724:59165857): proctitle=6E67696E783A20776F726B65722070726F63657373

More on NGINX or SELinux