bash (sh): Operation not permitted

Ran into an issue on another day when login as a normal user on an Oralce Linux 8 system. Once login, there were messages on the screen like

/bin/sh: /usr/libexec/grepconf.sh: Operation not permitted

It looks like loading the user’s shell profile which failed to exeute this script. It didn’t really affect what I was doing, but it’s annoying to see the message. So I decided to take a look. The script has the correct permission of 755 which means the user I was using should be able to execute it.

After some digging, I realized it’s caused by fapolicyd — a framework introduced in Redhat Linux 8 to control the execution of applications based on a user-defined policy as Redhat claims it as one of the most efficient ways to prevent running untrusted and possibly malicious applications on the system.

The fapolicyd framework introduces the concept of trust. An application is trusted when it is properly installed by the system package manager, and therefore it is registered in the system RPM database. The fapolicyd daemon uses the RPM database as a list of trusted binaries and scripts. The fapolicyd RPM plugin registers any system update that is handled by either the YUM package manager or the RPM Package Manager. The plugin notifies the fapolicyd daemon about changes in this database. Other ways of adding applications require the creation of custom rules and restarting the fapolicyd service.

The fapolicyd service configuration is located in the /etc/fapolicyd/ directory with the following structure:

  • The /etc/fapolicyd/fapolicyd.trust file contains a list of trusted files. You can also use multiple trust files in the /etc/fapolicyd/trust.d/ directory.
  • The /etc/fapolicyd/rules.d/ directory for files containing allow and deny execution rules. The fagenrules script merges these component rules files to the /etc/fapolicyd/compiled.rules file.
  • /etc/fapolicyd/fapolicyd.rules can also be used for rules.
  • The fapolicyd.conf file contains the daemon’s configuration options. This file is useful primarily for performance-tuning purposes.

To check current rules, use the command:

fapolicyd-cli --list

To adding a file into the trust list explicitly:

fapolicyd-cli --file add /usr/libexec/grepconf.sh

fapolicyd-cli --file add /usr/libexec/grepconf.sh --trust-file <my-app-list>

fapolicyd-cli --update

systemctl restart fapolicyd

–trust-file will store the corresponding entry to the “my-app-list” file under /etc/fapolicyd/trust.d/ directory. If this option is omitted, an entry is added into the /etc/fapolicyd/fapolicyd.trust file.

The method above might not be working if there is a rule defined to reject its execution. You can debug the execution of fapolicyd. First stop the fapolicyd, then start it in debug mode at the background

systemctl stop fapolicyd
fapolicyd --debug 2> fapolicy.output &

In my case, I was only interested in deny events, I can use:

fapolicyd --debug-deny 2> fapolicy.output &

and run your program, in my case just login as that user. Then bring fapolicyd into foreground and control-c to exit it.

fg
crtl-c

Then search “deny_audit” in the output file

root@joetest:# grep -i deny_audit fapolicy.output
rule=7 dec=deny_audit perm=open auid=1000 pid=157494 exe=/usr/bin/bash : path=/usr/libexec/grepconf.sh ftype=text/x-shellscript
rule=7 dec=deny_audit perm=open auid=1000 pid=157501 exe=/usr/bin/bash : path=/usr/libexec/grepconf.sh ftype=text/x-shellscript
rule=7 dec=deny_audit perm=open auid=1000 pid=157502 exe=/usr/bin/bash : path=/usr/libexec/grepconf.sh ftype=text/x-shellscript

So there is a rule number 7 defined in /etc/fapolicyd/fapolicyd.rules to reject execution of x-shellscript which you will aslo see when using “fapolicyd-cli –list”.

Then adding the following rule right above the rule number 7:

allow perm=open exe=/usr/bin/bash : path=/usr/libexec/grepconf.sh ftype=text/x-shellscript trust=0

trust=0 means the object (the part behind “:”) is not required in the trust database. “:” is used to seperate subject and object. For more information, check man page of fapolicyd rules with “man 5 fapolicyd.rules“. Then restart fapolicyd to pick up the new rules.

For my case, adding that rule didn’t work on Oracle Linux 8.5 and it always picked up the deny_audit rule after the allow rule I added which is against how fapolicd reads rules:

Rules are evaluated from top to bottom with the first rule to match being used for the access control decision.

I suspect it’s a bug within OL8.5 because I don’t see any troubles on OL 8.4 with the same fapolicyd rules.

Note if you install an application using rpm command, you need to refresh the fapolicyd RPM database manually with

fapolicyd-cli --update

Other useful commands:

Deleting the fapolicyd database:

fapolicyd-cli --delete-db

Dumping the fapolicyd database

fapolicyd-cli --dump-db

In rare cases, removing the fapolicyd pipe file can solve a lockup:

rm -f /var/run/fapolicyd/fapolicyd.fifo

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s