Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I moved a Perl CGI script from an old RedHat Linux box to a more recent CentOS Linux box and certain system commands no longer work.

for example system("ls -l filename"); works OK, but system("lp -d printer filename"); returns lp: Permission denied.

I have checked permissions on directories and files, I can run the same CGI script using sudo -u apache scriptname and then the troublesome systemcommands work fine.

So far as I can tell, Apache httpd isn't chrooted and there's nothing obvious in httpd.conf (which is almost as installed).

So why do I get lp: Permission Denied?

Here's a test script

use strict;
use warnings;
#use CGI::Carp qw(fatalsToBrowser);

  open (STDERR, '>&STDOUT') || die "cant merge STDERR $!\n";

print "Content-Type: text/plain\n\n";
print "TEST\n\n";
psys('which lp');
psys('ls -l /tmp/');
psys('ls -ld /usr /usr/bin /usr/bin/lp');
psys('ls -l /etc/alternatives/print-lp');
psys('ls -l /usr/bin/lp.cups');
psys('lp -d laser1 /tmp/');
psys('ls /home | wc -l');
print "Finished\n";

sub psys {
  my $command = shift;
  print "# $command\n";
  print "\n";

Here's what a browser receives


# id
uid=48(apache) gid=48(apache) groups=48(apache) context=user_u:system_r:httpd_sys_script_t:s0

# which lp

# ls -l /tmp/
-rw-r--r-- 1 apache apache 2309 Aug 30 15:59 /tmp/

# ls -ld /usr /usr/bin /usr/bin/lp
drwxr-xr-x 15 root root  4096 Sep 22  2011 /usr
drwxr-xr-x  2 root root 36864 Aug 30 12:06 /usr/bin
lrwxrwxrwx  1 root root    26 Mar 18  2011 /usr/bin/lp -> /etc/alternatives/print-lp

# ls -l /etc/alternatives/print-lp
lrwxrwxrwx 1 root root 16 Sep 22  2011 /etc/alternatives/print-lp -> /usr/bin/lp.cups

# ls -l /usr/bin/lp.cups
-rwxr-xr-x 1 root root 18792 Mar 30  2011 /usr/bin/lp.cups

# lp -d laser1 /tmp/
lp: Permission denied

# ls /home | wc -l
ls: /home: Permission denied

share|improve this question
I cannot reproduce this on my system with the script you gave. Does using the full path to lp work? ls is in /bin/ and lp is in /usr/bin. Perhaps the apache user does not have /usr/bin in its path? – terdon Aug 30 '12 at 16:30
@terdon: Same response to /usr/bin/lp ... ! – RedGrittyBrick Aug 30 '12 at 17:46
up vote 1 down vote accepted


It turns out I had selinux installed and enabled. With a bit of configuration the problem went away

Clues were

  • the string context=user_u:system_r:httpd_sys_script_t:s0 in the output of id
  • the presence of an selinux folder in /

I found a recipe for the solution at which caused me to check the audit.log - In there I noticed comm="lp" and denied (i.e. lp command denied)

Gory details follow in case they help anyone else

# grep 'comm="lp' /var/log/audit/audit.log | tail -n 2
type=AVC msg=audit(1346348949.002:30060): avc:  denied  { name_connect } for  pid=20130 comm="lp" dest=631 scontext=user_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:ipp_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1346348949.002:30060): arch=c000003e syscall=42 success=no exit=-13 a0=4 a1=2b0a50c0b108 a2=10 a3=7ffffa3aeba4 items=0 ppid=20123 pid=20130 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="lp" exe="/usr/bin/lp.cups" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)

# grep 'comm="lp' /var/log/audit/audit.log | tail -n 3 | audit2allow

#============= httpd_sys_script_t ==============
allow httpd_sys_script_t ipp_port_t:tcp_socket name_connect;

# grep 'comm="lp' /var/log/audit/audit.log | tail -n 3 | audit2allow -M secommands
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i secommands.pp

# ls secom*
secommands.pp  secommands.te

# /usr/sbin/semodule -i secommands.pp

# wget -O - http://localhost/cgi-bin/
--2012-08-30 19:05:09--  http://localhost/cgi-bin/
Resolving localhost...
Connecting to localhost||:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: `STDOUT'

    [<=>                                    ] 0           --.-K/s              TEST

# /usr/bin/lp -d laser1 /tmp/
request id is laser1-23 (1 file(s))

# ls /home | wc -l
ls: /home: Permission denied

    [ <=>                                   ] 2,034       --.-K/s   in 0.03s

2012-08-30 19:05:09 (56.9 KB/s) - `-' saved [2034]

The lp command works, I'm not really concerned about not being able to ls on /home - that's a security feature I like.

share|improve this answer
Well spotted :) – terdon Aug 30 '12 at 20:27

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.