linuxperlapache2.2mod-perl2qx

Certain binaries run while others don't (despite ls visibility and +x) from mod_perl2 script


On Apache 2.2 on CentOS 6.4 with perl 5.10.1.

I'm trying to get a remote directory listing from within a mod_perl script, which apparently (if I die qx(id)) is running as apache. But I'm not even getting as far as being able to run ssh without parameters, just to have it print its help info. So that's what I'm asking how to do in this question--it's not about ssh not being able to connect.

die qx(which ssh);

dies with:

/usr/bin/ssh

and:

die qx(ls -al /usr/bin/ssh);

dies with:

-rwxr-xr-x. 1 root root 376920 Feb 21  2013 /usr/bin/ssh

Okay, so, it can find it, and see it, and has execute rights on it (which is true for /usr/bin and /usr as well.) But then:

die qx(/usr/bin/ssh); # or just 'ssh'

dies with an empty array, so I tried:

system("ssh") == 0 or die "failed: $! (code $?)"; # or '/usr/bin/ssh'

...which dies with:

No such file or directory (code 65280)

Why is this? How can I get die qx(ssh) or die qx(/usr/bin/ssh) to die with the expected value of:

usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-e escape_char] [-F configfile]
           [-i identity_file] [-L [bind_address:]port:host:hostport]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-R [bind_address:]port:host:hostport] [-S ctl_path]
           [-W host:port] [-w local_tun[:remote_tun]]
           [user@]hostname [command]

Interestingly, from a bash prompt I get this:

$ sudo su apache ssh
This account is currently not available.

So...how can I run ls from an account that's not available, yet not ssh? They're both programs, why do they behave differently here?

Update: It's not just ssh, but I can't figure out the pattern: gawk, tar, and ping also don't work. Yet df, ls, dir, and pwd all do. But:

$ ls -al /bin/ls
-rwxr-xr-x. 1 root root 109208 May 23 07:00 /bin/ls
$ ls -al /usr/bin/dir
-rwxr-xr-x. 1 root root 109208 May 23 07:00 /usr/bin/dir
$ ls -al /bin/pwd
-rwxr-xr-x. 1 root root 28008 May 23 07:00 /bin/pwd
$ ls -al /bin/df
-rwxr-xr-x. 1 root root 73808 May 23 07:00 /bin/df

$ ls -al /bin/gawk
-rwxr-xr-x. 1 root root 375360 Aug  7  2012 /bin/gawk
$ ls -al /bin/tar
-rwxr-xr-x. 1 root root 390616 Feb 21  2013 /bin/tar
$ ls -al /usr/bin/ssh
-rwxr-xr-x. 1 root root 376920 Feb 21  2013 /usr/bin/ssh
$ ls -al /bin/ping
-rwsr-xr-x. 1 root root 40760 Jun  5 06:39 /bin/ping

So they all have all the 'x' bits set (except ping with its one 's', yet see below its error code), and for example, ssh and dir have identical ACLs. So why should ssh and gawk fail to give any output but dir and ls succeed? (Full paths or no.)

Update: even more perplexingly, /bin/gawk fails with the same message but code 256, and /bin/tar and /bin/ping similarly but code 512.

Update: OK, this part makes sense: If I run the failing binaries from the command line and then run echo $? immediately after, ssh gives 255, ping and tar give 2, and gawk gives 1. Those are scaled-down versions of what I get in mod_perl2. So, it seems to be that anything with a return code other than 0 doesn't work. Possibly it's outputting to STDERR, and so STDOUT doesn't capture anything, hence the blank return.

Aha, that's the answer--will post.


Solution

  • If you redirect STDERR to also capture it in your qx, like so:

    die qx(ssh 2>&1);
    

    ...you'll get the output you get on the command line. So it's not that it's not running, it's just that it doesn't write anything to STDOUT.