Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

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

#!/usr/bin/perl
use strict;
use warnings;
#use CGI::Carp qw(fatalsToBrowser);

BEGIN {
  open (STDERR, '>&STDOUT') || die "cant merge STDERR $!\n";
  $|=1;
}

print "Content-Type: text/plain\n\n";
print "TEST\n\n";
psys('id');
psys('which lp');
psys('ls -l /tmp/po-list.19025.ps');
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/po-list.19025.ps');
psys('ls /home | wc -l');
print "Finished\n";

sub psys {
  my $command = shift;
  print "# $command\n";
  system($command);
  print "\n";
}

Here's what a browser receives

TEST

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

# which lp
/usr/bin/lp

# ls -l /tmp/po-list.19025.ps
-rw-r--r-- 1 apache apache 2309 Aug 30 15:59 /tmp/po-list.19025.ps

# 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/po-list.19025.ps
lp: Permission denied

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

Finished
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

selinux!

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 http://www.thedumbterminal.co.uk/php/knowledgebase/article/131 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/t4.pl
--2012-08-30 19:05:09--  http://localhost/cgi-bin/t4.pl
Resolving localhost... 127.0.0.1
Connecting to localhost|127.0.0.1|: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/po-list.19025.ps
request id is laser1-23 (1 file(s))

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

Finished
    [ <=>                                   ] 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

You must log in to answer this question.

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