aspose file tools*
The moose likes Linux / UNIX and the fly likes Super user on unix not honoured by Java? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » Linux / UNIX
Bookmark "Super user on unix not honoured by Java?" Watch "Super user on unix not honoured by Java?" New topic
Author

Super user on unix not honoured by Java?

Smarto Chandra
Greenhorn

Joined: Jul 12, 2006
Posts: 4
Hi,

When the super user is executing a Java program, does Java still treat them as a normal user from the point of view of file permissions? I came to this conclusion based on my following experiment -

The small program below runs whatever command it receives as program arguments -

/******** Start program listing *********/

import java.io.*;
public class ExecCommand {

public static void main(String[] args) {
try{

if(args.length == 0)
{
System.out.println("Nothing to execute - usage is \"java ExecCommand command [arg1] [arg2] ...\"");
}
else
{
Process p = Runtime.getRuntime().exec(args);
BufferedInputStream r = new BufferedInputStream(p.getInputStream());
int c = (char)r.read();
while(c >= 0)
{
System.out.print((char)c);
c = r.read();
}
}
System.exit(0);
}
catch(Exception e){
e.printStackTrace();
}
}
}

/********* End program listing **********/

On trying this program on my Linux system, I got the following output -

/******** Start console listing *********/

root@zorro ls -l
total 12
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro java ExecCommand date
Wed Jul 12 22:09:04 IST 2006
root@zorro java ExecCommand ls -l
total 12
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro java ExecCommand ./tp
java.io.IOException: java.io.IOException: ./tp: cannot execute
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at ExecCommand.main(ExecCommand.java:12)
root@zorro ./tp
Hello World
uid=0(root) gid=0(root) groups=0(root)
root
root@zorro cat tp
#!/bin/sh
echo "Hello World"
id
echo $USER
root@zorro

/********* End console listing **********/

So the superuser can run a script on which it doesn't have the requisite permissions, but Java seems to disallow this. Or am I missing something obvious? I would be really glad if someone can help me understand this behaviour better.

Thanks in advance,
Smarto
[ July 13, 2006: Message edited by: Smarto Chandra ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Hi,

Welcome to JavaRanch!

I tried your example and I'm very puzzled. At first I couldn't imagine what was going on, but then I began to suspect that perhaps it's an obscure security rule due to the fact that it's a shell script you're running.

If you use a binary program instead (for example, make a copy of /bin/ls, and change the permissions) then it works fine. It also works if you run "sh -c ./tp" instead of just ./tp. So your guess doesn't seem to be right.

I'm going to move this to our Linux/UNIX forum, and maybe someone there knows what the obscure rule is!


[Jess in Action][AskingGoodQuestions]
Smarto Chandra
Greenhorn

Joined: Jul 12, 2006
Posts: 4
Hi Ernest,

Thanks for replying, the warm welcome and for pointing me to the right forum.

I am not sure if my problem has to do with the exact Unix flavour, but I run into it even with binaries. See the listing below -

/******** Start console listing *********/

root@zorro cp /bin/sh .
root@zorro cp /bin/ls .
root@zorro ls -l
total 676
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-xr-x 1 root root 68660 Jul 12 23:30 ls
-rwxr-xr-x 1 root root 598580 Jul 12 23:30 sh
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro ls -l /bin/ls /bin/sh
-rwxr-xr-x 1 root root 68660 Aug 12 2003 /bin/ls
lrwxrwxrwx 1 root root 4 Aug 12 2003 /bin/sh -> bash
root@zorro cksum /bin/ls
3040629578 68660 /bin/ls
root@zorro cksum /bin/sh
1064254817 598580 /bin/sh
root@zorro cksum ./sh
1064254817 598580 ./sh
root@zorro cksum ./ls
3040629578 68660 ./ls
root@zorro chown smarto : dev ./sh ./ls
root@zorro chmod 750 ./sh ./ls
root@zorro ls -l
total 676
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 68660 Jul 12 23:30 ls
-rwxr-x--- 1 smarto dev 598580 Jul 12 23:30 sh
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro java ExecCommand ./ls
java.io.IOException: java.io.IOException: ./ls: cannot execute
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at ExecCommand.main(ExecCommand.java:12)
root@zorro java ExecCommand sh ./tp
Hello World
uid=0(root) gid=0(root) groups=0(root)
root
root@zorro java ExecCommand ./sh ./tp
java.io.IOException: java.io.IOException: ./sh: cannot execute
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at ExecCommand.main(ExecCommand.java:12)
root@zorro uname -a
Linux zorro 2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686 i386 GNU/Linux
root@zorro cat /etc/redhat-release
Red Hat Enterprise Linux AS release 3 (Taroon)
root@zorro

/********* End console listing **********/

Thanks also for the "sh -c ./tp" idea. In this case, it is /bin/sh which the program is executing and the owner and permissions on that are such that I do not face a problem.

Just to be sure, had you also changed the owner (along with the permissions) of the copy of /bin/ls before trying it out?

Best regards,
Smarto

[ July 12, 2006: Message edited by: Smarto Chandra ]
[ July 12, 2006: Message edited by: Smarto Chandra ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Originally posted by Smarto Chandra:

Just to be sure, had you also changed the owner (along with the permissions) of the copy of /bin/ls before trying it out?


Yes.

You're using RHE3, and I'm running Fedora Core 3; it's possible it has something to do with SELinux, which both distros include some variation of; perhaps we have different, if similar, settings. I'm not an expert in the security arena so I can't comment.
Stefan Wagner
Ranch Hand

Joined: Jun 02, 2003
Posts: 1923

I don't understand where the problem is too, but I would expect a permission-denied-message if it was a security problem, not an IO/ - cannot execute.

(Edit

You already found out?
root@zorro ls -l
total 676
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 68660 Jul 12 23:30 ls
-rwxr-x--- 1 smarto dev 598580 Jul 12 23:30 sh
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro java ExecCommand ./ls

Owner=smarto, group=dev - of course root can't execute ./ls ./sh ./tp.
[ July 13, 2006: Message edited by: Stefan Wagner ]

http://home.arcor.de/hirnstrom/bewerbung
Smarto Chandra
Greenhorn

Joined: Jul 12, 2006
Posts: 4
Hi Stefan,

Thanks for your reply. The problem is that root can execute those commands when they are not being run by the Java program. See the listing below -

/******** Start console listing *********/

root@zorro ls -l
total 676
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 68660 Jul 12 23:30 ls
-rwxr-x--- 1 smarto dev 598580 Jul 12 23:30 sh
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro ./ls
ExecCommand.class ExecCommand.java ls sh tp
root@zorro ./ls -l
total 676
-rwxrwxr-x 1 root root 1009 Jul 12 22:07 ExecCommand.class
-rwxrwxr-x 1 root root 585 Jul 12 22:06 ExecCommand.java
-rwxr-x--- 1 smarto dev 68660 Jul 12 23:30 ls
-rwxr-x--- 1 smarto dev 598580 Jul 12 23:30 sh
-rwxr-x--- 1 smarto dev 43 Jul 12 21:31 tp
root@zorro ./sh date
date: /bin/date: cannot execute binary file
root@zorro ./sh ./tp
Hello World
uid=0(root) gid=0(root) groups=0(root)
root
root@zorro ./tp
Hello World
uid=0(root) gid=0(root) groups=0(root)
root
root@zorro java ExecCommand ./sh ./tp
java.io.IOException: java.io.IOException: ./sh: cannot execute
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at ExecCommand.main(ExecCommand.java:12)
root@zorro java ExecCommand ./ls
java.io.IOException: java.io.IOException: ./ls: cannot execute
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:491)
at java.lang.Runtime.exec(Runtime.java:457)
at ExecCommand.main(ExecCommand.java:12)
root@zorro

/********* End console listing **********/

So maybe it's a Linux problem after all, I'm not sure.

Regards,
Smarto
Stefan Wagner
Ranch Hand

Joined: Jun 02, 2003
Posts: 1923

Ah yes - now I see.

And I can reproduce it:


So the question is: "Why is root allowed to run the program directly?" - not: "Why isn't he allowed to run them with java?"


suspicious, suspicious, ...
[ July 13, 2006: Message edited by: Stefan Wagner ]
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16011
    
  19

root is applied at the OS level. Java, being "write-once, run anywhere" has no magic powers. In fact, you'll discover than certain common OS functions can't be done in Java for the sole reason that they're OS functions and not OS-independent functions.

One of the biggest offenders was the ENVIRONMENT. Almost all OS's support environment variables, but Java was forbidden to read them because it was "almost all" instead of "all". Also, I think for security reasons, but that's another story. I think after years of angry howling, Sun finally gave in on that one, since an ENVIRONMENT-free OS is degenerate case where the enviroment's always empty. However file ownership, access rights (or ACLs) and such are notoriously unportable, so the java.io package doesn't support them.


Customer surveys are for companies who didn't pay proper attention to begin with.
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Originally posted by Tim Holloway:
However file ownership, access rights (or ACLs) and such are notoriously unportable, so the java.io package doesn't support them.


Sorry, but I don't buy that as an explanation. "Not supporting them" would mean just ignoring them, and that's exactly what I'd expect the JVM to do. It should try to execute the program, and if it succeeds, it succeeds because the execXX() call allowed it. If it fails, it only fails if execXX() didn't allow it. But here we see a case where it's clearly legal to execXX() a program, but the JVM won't do it.
Stefan Wagner
Ranch Hand

Joined: Jun 02, 2003
Posts: 1923

I have to apologize for remarks, based on bad information.
I thought root woulndn't be able to execute files without matching flag as owner, group or other.

In fact the owner of a file may not read it, if the flag is not set, without giving himself the permissions first.
But now I see it is normal, that root may execute a file, if anybody has permission to execute it.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16011
    
  19

Originally posted by Ernest Friedman-Hill:


Sorry, but I don't buy that as an explanation. "Not supporting them" would mean just ignoring them, and that's exactly what I'd expect the JVM to do. It should try to execute the program, and if it succeeds, it succeeds because the execXX() call allowed it. If it fails, it only fails if execXX() didn't allow it. But here we see a case where it's clearly legal to execXX() a program, but the JVM won't do it.


I can't follow that. "execXX" sounds like Runtime.exec(), and that's an acceptable rathole, but java.io is part of the "write once run anywhere" part, and if you were to provide a set of ACL functions, allowed them to be called, but didn't do what you claimed you were doing (that is, provided a specific set of protections), you'd be creating pseudo-portable code. Which is to say, code that appeared to work, but had major security and functional issues on some platforms. Thus, Sun won't even permit the illusion of ACL support in strictly conformant Java.

Another problem with Java supporting ACLs is that there are a lot of different implementations of the concept. I'm not even sure the Linux and Solaris ones are that similar, IBM's RACF is a completely different concept, and the old Honeywell GCOS systems had ACLs and CACLS. And then there's Microsoft.
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

execXX() meaning the UNIX exec() family of system calls: execve(), execl(), execle(). I didn't want to just say exec() because then you would indeed think I meant the Java call.

What's seemingly been demonstrated here is that the JVM looks at the file permissions on a file (which are otherwise inaccessible from Java) and chooses whether or not to execute that file; the JVM seems to make this choice in a way which is at odds with what the OS does if you ask the OS directly. It doesn't make any sense to me that the JVM would implement its own permissions system...

... And yet, it does. I've just gone off and rooted about in the JDK source, and lo and behold, the implementation of Runtime.exec() does, indeed, check the executability of a file before trying to fork/exec it; and in my opinion, the check is wrong. In the Java 5 source, forkAndExec() (in j2se/src/solaris/native/java/lang/UNIXProcess_md.c) calls fullPath() to find the executable, which calls statExecutable(), which makes the following extremely lame check:



In other words, if we own this file, then check the user execute bit; if not, but we're in the same group, then check the group execute bit; if neither, then check the "other" execute bit. There's no special case for root, so root can't execute files it doesn't own! Even though the execve() would succeed, Java won't even try.

Smarto Chandra, if I were you, I'd go over to the bug database (http://bugs.sun.com/bugdatabase/index.jsp) and file a bug report, because I don't think this is right.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Super user on unix not honoured by Java?