I am trying to setup my computer to notify me every time a user logs in (via ssh, via gdm or tty). Right now I am setting up sshd and I added this to /etc/pam.d/sshd:

session optional pam_exec.so /etc/pam_scripts/notify.sh

This is optional because I still want to login via ssh even if the command fails for some reason.

First: I placed this row after pam_selinux close and before pam_selinux open, as suggested here.

If I place a whoami in the script and I log the execution, I can see that the command is run asroot`, and in particular:

uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:sshd_t:s0-s0:c0.c1023

The problem is that, from the logs, I can see selinux preventing the execution of curl, which is used inside the script:

AVC avc:  denied  { name_connect } for  pid=1810 comm="curl" dest=443 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=0

My script has this label:


I tried changing the context using chcon, but I always get permission denied (even using root), so I am probably doing something I don't fully understand.

BTW, I also tried using seteuid in the pam rule, but nothing changed.

In general, I don't understand how do I determine which is the required context of the script for selinux granting execution access.

Also, this seems more related to curl than the script itself, since the script runs properly, but it is curl that is stopped by selinux.

How do I fix this problem?

2 Answers 2


I see you found an answer already, but since I was working on this I'll leave it here for posterity:

When you run into an selinux denial like that, you can use the audit2allow tool to generate an updated selinux policy that will permit that action. First, you probably want to put selinux into permissive mode:

setenforce 0

Now, log in and make sure your PAM configuration works as expected. We do this because there's a good chance that there may be additional selinux denials after the first one, and running in permissive mode will make sure they all get logged.

Now you can put selinux back into enforcing mode:

setenforce 1

Run audit2allow -a. This will generate something like the following:

#============= sshd_t ==============

#!!!! This avc can be allowed using one of the these booleans:
#     authlogin_yubikey, nis_enabled
allow sshd_t http_port_t:tcp_socket name_connect;

I say "something like" because (a) as I said earlier there may be additional denials related to your current PAM configuration and (b) this command looks at all entries in the audit log, so you get get results for previous denials that aren't actually related to your current issue.

In this case, we see that we can permit the action that was denied by setting an existing selinux boolean. That would look something like:

setsebool nis_enabled=1

That may be all that you need. Alternatively, you can generate an update to your selinux policy like this:

audit2allow -a -M local

This will generate a new policy file local.pp. You can activate that by running:

semodule -i local.pp

There is some good information about working with selinux here, including a much more detailed overview of using audit2allow.

  • audit2allow seems very useful, thanks a lot!
    – AkiRoss
    Nov 12, 2019 at 13:27
  • I'll accept your answer anyway, as it is useful even if I resolved the issue.
    – AkiRoss
    Nov 12, 2019 at 13:28

Ok, it took me a while, but I managed to fix it. My problem is that I did not know how to check for selinux rules, after reading the excellent Gentoo SELinux tutorial I found out how to query the rules using sesearch:

# sesearch --allow -s sshd_t -t unreserved_port_t -c tcp_socket -p name_connect

In this case, I switched my notification script from a known port to a random port, this is why I am serarching unresolved_port_t as a target type instead of the http_port_t target I reported from the audit log.

In the list, there is this rule:

allow sshd_t unreserved_port_t:tcp_socket name_connect; [ nis_enabled ]:True

This is allowed, but subject to the boolean nis_enabled which was, in fact, disabled on my system (checked via getsebool -a | grep nis_enable).

I used setsebool nis_enabled on to enable that rule and it is working flawlessly now.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .