When we run Runtime.exec(cmd), what user will it be run from? For example, user1(on Unix) ran java -jar Test.jar. In this program we have Runtime.exec("whoami"). Which user id shall we recieve?
I have screen'd terminal, where was ran chrootuid cmd and there is running java program. And somehow, whoami command from this pr. returns NOT SAME user id as chrootuid's owner, from which name was J.p. ran. Can anybody explain this?
All child processes run as the same user as the parent process.
As #SLaks says, the script will be run as the same user which has launched the JVM in the first place.
Rundown:
the JVM is launched within a process;
this process has plenty of data inherited from its parent, along which the user which launched it;
the standard Java API has no way to modify the user;
even if it had such power, changing the running user would require elevated privileges anyway.
So, there you are: the "forked" process will run with the same credentials as the JVM.
Now, some more information on running a separate process in general...
In Java, you really want to use a ProcessBuilder instead of Runtime.exec(), for the following reasons:
it allows you to control I/O output;
it allows you to specify command line arguments "the right way" (think: argument with spaces);
it allows you to defer execution (.start()).
But it clearly does not allow you fine-grained control of shared resources, nor privilege modifications, as native APIs can do. Still, ProcessBuilder is better than Runtime.exec() by a large margin, but Java is yet to experience a radical change for process handling as the new java.nio.file is to File: a revolution.
Related
We can view bash commands history. It is stored normally in ~/.bash_history. For the same reason it is not recommended to send a curl request along with certificates and passwords.
But when I execute the same curl command using Runtime class in java Runtime.getRuntime().exec(command); I don't see this in the bash history.
It makes sense as this is done under the Runtime object and not executed from terminal. So where can I get the history of curl when done from Java using Runtime class?
Also is it safe to use Runtime class instead of actually storing certificate in a Trustore and using Https related Java classes?
Note: The certificates will be kept securely in Jenkins anyways.
How to view history of curl command executed using Runtime.getRuntime().exec?
You didn't run it with bash so, no, it is not in bash history. The answer to your question is OS dependent (and 'linux', in this sense, isn't detailed enough. What kind?) But, for example, as long as the command is running, ps auxww will probably show it, with the full command line including the arguments. As long as it is running, the directory representing the status of the process in the /proc virtual filesystem definitely lets you see the arguments it was invoked with.
Also is it safe to use Runtime class instead of actually storing certificate in a Trustore and using Https related Java classes?
That's just not how security works. It's shades of gray, not black and white. However, starting a subprocess for this is definitely a much darker gray (far less safe) than using java itself: As long as it is running, that subprocess arguments can be seen. The version of whatever command you invoke is less controllable (are you going to hash the executable? How would you know that the executable isn't being changed on you? This is of course entirely fine if you know who administrates the box and trust them, but that gets back to that shades of gray thing: If that part doesn't matter, sure, then this part is less problematic (heck, if you are the only one with an ssh login to this box, and only run trusted software, you can write the password across 50 files with global readability all over the file system and it wouldn't matter - and yet nobody is going to go on record and just make a blanket statement that this is 'safe'!).
This question is not as simple as telling me to use runas; Please read the question before answering.
When I use C on UNIX/Linux and want to write a program to run with elevated privilege, I use this flow:
program starts.
process lowers privilege using setuid().
process does unprivileged work.
process raises privilege using
setuid().
process does privileged work such as opening a
restricted file.
process lowers privilege using setuid().
The critical part of the flow is that the process lowers its privilege immediately after starting and only raises its privilege long enough to do the corresponding work.
How can I do a similar thing on Windows using Java?
My specific use case is that I want to read and write protected files such that the only way for the user of the program to access the files is thru my Java program. I do not want to run the entire process with Administrator privilege just to protect a couple of files.
The JRE by itself does not allow this. There are two options to do it in "Java":
Use JNI to make C calls into the OS
Script out the calls that use setuid() (use a script language or create a C executable) and have the JVM exec that script.
I believe the more difficult part of your problem will be finding a setuid() equivalent in Windows. See https://serverfault.com/questions/16886/is-there-an-equivalent-of-su-for-windows. The most straightforward way would be to wrap runas (yes, I said it) in a script or perhaps exec your script with runas. See Run command prompt as Administrator for ideas on how to do that.
I was wondering if anybody knew with any certainty whether ProcessBuilder/Runtime.exec() executes inside the space of the JVM's memory or whether it uses completely separate system memory and somehow sends the output to Java. I could not find any documentation on the subject.
I assume it is the former due to security issues and being able to read output, but I would like to make absolutely sure.
The new process runs outside the Java process that started it. Allocation of memory to the new process is managed by the operating system, as part of process management.
The Java class ProcessBuilder, which provides an interface for starting and communicating with the new process, runs inside the Java process.
Seems pretty clear that exec launches a new process, or program for those not versed in operating system terminology. That's why it has input output facilities, ability to set the environment, and ability to wait on the external program returning.
The first line of the javadoc says it all.
Executes the specified string command in a separate process.
The command argument is parsed into tokens and then executed as a command in a
separate process. The token parsing is done by a StringTokenizer created by the
call:
new StringTokenizer(command)
with no further modifications of the character categories. This method has exactly
the same effect as exec(command, null).
From the concurrency reference of Java SE, it is said that:
A process has a self-contained execution environment. A process
generally has a complete, private set of basic run-time resources; in
particular, each process has its own memory space.
If you are interested in the internals, check the UNIXProcess class from the openJDK.
Is it possible to stop an application in windows using java code ?
I'd like to create a program which is like a shortcut to stop an application on my pc. Is it possible using ProcessBuilder ? Thank you
Plain Java, without native access? No.
ProcessBuilder lets you control processes that you started from within the Java application, but it doesn't give you control to processes that were started by other processes.
As per user988052's comment, you can use pskill from the Sysinternals Suite to accomplish this through Runtime.exec. pskill uses the TerminateProcess function call. You can also call this function with JNI (or some other native caller, like JNA, NLink, etc.), but you'll need to obtain a handle to the process via the OpenProcess function call.
Is it possible to stop an application in windows using java code ? ... Is it possible using ProcessBuilder ?
Only if you launched the application from the same Java application that you are trying to fill it from.
Other than that, you need to resort to running a Windows-specific command to do the killing ... or something based on JNI to make native Windows library calls.
The other complications are that you may not be able to kill certain processes due to permissions issues, and some process may refuse to be killed.
I believe the JRE does not provide an API for system processes. ProcessBuilder can create system processes, but it cannot provide you with a Process object for a process created outside the JVM. I believe that is a philosophical decision on the part of the Java folks, to avoid certain OS-specific tasks where possible. You might think that every OS has pids, or that they all have some kind of kill message, but Java runs on lots of OSes, some of them quite strange.
You could make native code to do it and wrap that with JNI, but that would be wasteful. As Mr 988052 says, I suggest you execute a system-specific command through Runtime.exec or ProcessBuilder. You would need to decide which OSes you want to support, and be sure to get the commands (and the OS-detection code) right for each one.
Can a Java.exe JVM restart itself somehow? If you have a Java program running in a DOS shell (NOT as a service), what is the cleanest, most efficient way for it to shut down, close the shell, and restart itself with a different Windows process id and re-open in a different shell with a reloaded classpath?
I expect it's not possible but I thought I should ask and learn from other people by asking.
NOTE: If anyone knows how Eclipse IDE is able to restart itself so cleanly, that is the method I am wanting to use.
The Java Service Wrapper can help here. You can run your Java process under it but not necessarily as a service. You can define restart characteristics, such that if it exits, the Java program is restarted (either by System.exit() or calling WrapperManager.restart()).
The cleanest and simplest way to do that would be to run the program from a DOS batch file (or CMD script, if you prefer). Build a loop into your DOS batch file. You put a :label near the beginning and a GOTO label below your Java process and off it goes. If need be, you can break out of the loop using Ctrl-C.
Create a separate executable that takes a process ID and a command as command line argument, waits for the specified process to close and then runs the specified command. Launch that program, then exit the current instance.
You can either embed that program in your primary program and copy it to a temporary directory to execute it, or include it side-by-side with your program.