./sqlplus: error on libnnz11.so: cannot restore segment prot after reloc

The Problem

Immediately after a successful RDBMS installation (perhaps even including a sample DB instance creation), sqlplus will not start:

./sqlplus / as sysdba
./sqlplus: error while loading shared libraries: $ORACLE_HOME/lib/libnnz11.so: cannot restore segment prot after reloc: Permission denied

This can occur on any Oracle application and can display against any shared library.

The Solution

SELinux is running in “enforcing” mode. A potential solution is to change the default context of the affected oracle libraries to textrel_shlib_t:

/usr/sbin/semanage fcontext -a -t textrel_shlib_t $ORACLE_HOME/lib/libnnz11.so
/usr/sbin/semanage fcontext -a -t textrel_shlib_t $ORACLE_HOME/lib/libnque11.so
/usr/sbin/semanage fcontext -a -t textrel_shlib_t $ORACLE_HOME/lib/libclntsh.so.11.1

This only sets up rules for labeling and does not actually apply those rules. These context assignments should be applied with the “/sbin/restorecon {filename}” command. Please contact your Linux OS support provider for additional details on configuring SELinux. When finished, you can then verify that the context change took place by re-trying sqlplus.

Although this approach does have the benefit of leaving SELinux enabled and “enforcing” on the remainder of the system, it also presumes that the Customer can identify all of the affected oracle libraries that are involved in the compiler version compatibility issue. Since this is not a wise presumption, Oracle Development has instead recommended the following workaround:

Switch SELinux from the default “Enforcing” mode that it is running in, to the “Permissive” mode.

Commands, as root:
getenforce       (returns "Enforcing")
setenforce 0
getenforce       (returns "Permissive")

This allows SELinux to continue running, and logging denial messages, but SELinux will not actually deny any operations. Once Development has resolved this issue, you can (and should) return SELinux to the default “Enforcing” mode as follows:

Commands, as root:
setenforce 1
getenforce       (returns "Enforcing")

The commands for the work-around above are immediate, and will remain in effect until the next reboot. Please also ensure that SELinux “Permissive” enforcing is set at boot time by adding “enforcing=0” to the kernel boot line. An example of setting the SELinux mode to permissive from GRUB could be as follows:

title Red Hat Enterprise Linux ES (2.6.18-8.EL)
root (hd0,0)
kernel /vmlinuz-2.6.18-8.EL ro root=/dev/VolGroup00/LogVol00 rhgb quiet enforcing=0
initrd /initrd-2.6.18-8.EL.img

Although not recommended, SELinux could also be completely disabled if desired.