Fork and drop privileges with Java - java

I'm writing a server program in Java that will allow users to submit jobs using DRMAA. Although the main server process runs as root, all it does is authenticate the user, then start another Java program which runs as that user and actually does the work in order to comply with the principle of minimising privileges. Initially, I was doing this with Runtime.exec() and sudo (example below) which works fine until the process is dæmonised, at which point sudo gets upset because it doesn't have a terminal.
String[] command = {"sudo", "-i", "-u", username, java, theOtherJavaProgram};
Runtime.getRuntime().exec(command, null, getHomeDirectory(username));
What's the best way to do this fork and drop privileges pattern in Java when running as a daemon? Is there a way? Am I going to have to break out the C and learn how to create JVMs with JNI?

It's probably easier to just use JNI to drop privileges.
Here's one I knocked up earlier:
UID.java
public class UID {
public static native int setuid(int uid);
static {
System.loadLibrary("uid");
}
}
unix_uid.c
#include <sys/types.h>
#include <unistd.h>
#include <jni.h>
#include "UID.h"
JNIEXPORT jint JNICALL
Java_UID_setuid(JNIEnv * jnienv, jclass j, jint uid)
{
return((jint)setuid((uid_t)uid));
}
UID.h is machine generated from UID.class using javah.

You could use su(1) instead of sudo(8). su(1) is much less involved, and probably won't want the terminal itself. (Of course, if your PAM configuration requires terminal input for su(1), then this might not work well either.)

If you only want to start a non-root process as root, then su will be sufficient. It will not ask for a password when going from root to another user, so it should not need a terminal.

Related

assigning linux capability to one java process

I run many java processes but I just want to assign cap_net_raw linux capability to just one java process.
Currently if I do this "setcap cap_net_raw=ep /usr/java/default/bin/java" then this capability get assigned to all java processes.
After doing some research, I figured that I will have to write a c wrapper program and give above mentioned capability to that program and java process will inherit in execv.
Another research says that capability can be assigned through systemd.
I am not sure how to use systemd capability option and if it's a viable option.
Can someone please guide me which way to go and how exactly to do it? Thanks
I wrote a wrapper (using another stackoverflow article) to achieve this.
capjava.c:
#include <sys/capability.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv[]) {
char *cmd;
char **argvp;
int ret = 0;
cap_t caps = cap_get_proc();
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_value_t newcaps[1] = { CAP_NET_RAW, };
cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
cap_set_proc(caps);
printf("\nNew Capabilities: %s\n", cap_to_text(caps, NULL));
cap_free(caps);
argvp = &argv[1];
cmd = argvp[0];
printf("cmd is %s\n", cmd);
ret = execv(cmd, argvp);
printf("\n return value of execv is %d\n", ret);
}
Now added permissions:
[root#localhost ~]# setcap cap_net_raw=p /sbin/capjava
[root#localhost ~]# setcap cap_net_raw=ei /usr/java/latest/bin/java
added capjava in systemctl config file for one of my application.

Write & call Swift code using Java’s JNI

As you see here one can perform native C/C++ method calls from Java code, thanks to JVM’s JNI. But how about performing calls of Swift methods? Is this possible or going to be possible (can be implemented in a reasonable time frame) as Swift becomes more popular?
I want to access Apple’s native API that is only accessible when one writes apps in either Objective-C or Swift. As the JVM is just being ported to ARMv8 (64-bit), I could also imagine the JVM as an alternative runtime for iOS apps in the future. But this might be the future... The present is: The JVM runs on Mac OS X and one can write apps for Mac OS X in Swift that can access some APIs that might be not accessible to Java apps in the same way.
Well, roughly 5½ years later, it turned out, it wasn't the future... No JVMs on iOS.
But you can definitely do it, i.e., call Swift APIs from Java. That said, it's quite cumbersome, because AFAIK, you have to take a detour via C/C++.
Here's the deal:
As you know, you can use JNI to call C code.
From C you can call Swift.
The following relies heavily on this question.
Code
Your Java code is in helloworld/SwiftHelloWorld.java:
package helloworld;
public class SwiftHelloWorld {
static {
System.loadLibrary("SwiftHelloWorld");
}
public static native void printHelloWorldImpl();
public static void main(final String[] args) {
printHelloWorldImpl();
}
}
Now write the native C code (file helloworld_SwiftHelloWorld.c):
#include <jni.h>
#include <stdio.h>
#include "helloworld_SwiftHelloWorld.h"
#include "helloworld_SwiftHelloWorld_swift.h"
JNIEXPORT void JNICALL Java_helloworld_SwiftHelloWorld_printHelloWorldImpl
(JNIEnv *env, jclass clazz) {
int result = swiftHelloWorld(42);
printf("%s%i%s", "Hello World from JNI! ", result, "\n");
}
Which uses a header file named helloworld_SwiftHelloWorld_swift.h for our (yet to be written) Swift code:
int swiftHelloWorld(int);
Finally, our Swift code resides in SwiftCode.swift:
import Foundation
// force the function to have a name callable by the c code
#_silgen_name("swiftHelloWorld")
public func swiftHelloWorld(number: Int) -> Int {
print("Hello world from Swift: \(number)")
return 69
}
Building
To build all this, we first have to compile the Swift code to a dynamic library:
swiftc SwiftCode.swift -emit-library -o libSwiftCode.dylib -Xlinker -install_name -Xlinker libSwiftCode.dylib
We use the -Xlinker directives to ensure that the dylib's location is relative.
Before we can create the C dylib, we first have to generate the Java headers:
javac -h . helloworld/SwiftHelloWorld.java
Now that we have the Java headers and the Swift dylib, we can compile the C dylib, which links against the Swift dylib:
gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSwiftHelloWorld.dylib -dynamiclib helloworld_SwiftHelloWorld.c libSwiftCode.dylib
Now that everything is in place, we must make sure that both dylibs are in the same directory and that that directory can be found by Java, i.e., you may need to set -Djava.library.path=<dir of your dylibs>.
Et voilà!
Swift called from Java!

Porting a CPP application to Android

I need to port a CPP project to Android but I somehow got stuck because of the following things that I am not sure of:
Do I need to use some kind of java wrapper for my CPP project at all, i.e is it necessarily that I use Android SDK to integrate my application with Android? If there is another way, which one would that be?
I have seen some people claiming they have been able to manipulate their cmake file and some custom android-cmake toolchain to build their “.so” or eventually an “.apk” from their project. Would it be possible without a java wrapper to manipulate the cmake files of the cpp project to build your project? (source: Build Android NDK project with Cmake)
From my experience, I would go with using the android java entry point, otherwise you will most likely bump into problems (you can make full native android apps , but I strongly advise against it).
One of the reasons is that you will want SDK function calls from inside your CPP, and using reflection on the java environment from CPP isn't trivial.
The steps would be the following :
Create a very simple C code that will server as bridge to your CPP code . Here are some sample C functions that I've commonly used :
OnApplicationStart
OnApplicationPaused
OnApplicationResumed
OnApplicationUpdate
OnTouchReceived
Export these functions and load them in your Java code (lookup JNI on how to do this)
Handle all Android-specific actions in Java, and all application specific actions in cpp
So the answer to your 1st question is that a java wrapper isn't mandatory, but it's HIGHLY recommended.
To answer your 2nd question :
Yes, you can use cmkae, ant, cygwin , allot of command tools that will end up creating your apk (It's up to you on how you feel comfortable).You will still use the android compiler since you are targeting arm.
The difference is that you need to change in your manifest.xml the entry point of the application from a normal activity to a native activity ( http://developer.android.com/reference/android/app/NativeActivity.html ) .
As you can see, the difference isn't the build system, it's the way you define your entry point.
As a friendly advice, try using the minimal java wrapper approach. You might get to better results sooner, and it won't take you more then 1 week of research on the web on how to link java code to cpp.
EDIT :
As of demand, I will shortly explain how I would approach the process of porting a CPP application to Android :
Rethink your application to work as a shared library , using a C entry point :
a.Create a simple C application that will load yourCPPApp.dll (or .so if you are on linux)
b. In your .dll create the minimum necessary extern "C" functions to be exported in order for you to give the necessary information to your dll
For simplicity, we'll assume we have 3 methods :
void StartApplication();
bool OnApplicationUpdate();
void OnScreenTouched(int x, int y);
c. Implement the simple C project that will make the calls to these methods externaly (so the .exe will call the methods from the .dll ! )
Sample code :
#include "myCPPapp.h"
int main(int arg, char** argv)
{
StartApplication();
srand(time(NULL));
while (OnApplicationUpdate())
{
// we assume we have a 480x640 resolution
OnScreenTouched(rand()%480,rand()%640);
}
return 0;
}
Now that we have things working in full native with a .exe and a .dll , time to make it work with a .apk and a .so
a. Rename the exposed methods from myCppApp into java compatible prototypes
extern "C" {
JNIEXPORT void JNICALL Java_com_sample_nativebridge_OnApplicationStart(JNIEnv env, jobject thiz);
JNIEXPORT jboolean JNICALL Java_com_sample_nativebridge_OnApplcationUpdate(JNIEnv env, jobject thiz);
JNIEXPORT void JNICALL Java_com_sample_nativebridge_OnScreenTouched(JNIEnv env, jobject thiz, jint x, jint y);
}
b. create the java class nativebridge (case sensitive) in the package com.sample (you need t respect the names in order for correct linkage to native)
class nativebridge {
public static native void OnApplicationStart();
public static native boolean OnApplicationUpdate();
public static native void OnScreenTouched(int x, int y);
}
c. add the load library statement in the native bridge in order to have your library loaded at runtime
class nativebridge {
....
static {
System.loadLibrary("myCppApp");
// notice that the lib prefix and .so sufix aren't part of the name
}
}
d. compile your CPP code with the armeabi compiler and create libmyCPPApp.so (ndk build system , or whatever you'd like... i would go with the ndk, it's quite easy , just go into the folder with Android.mk and call $ANDROID_NDK_BUILD_PATH/build )
At this point you will need to createa a .mk file that will compile your myCppApp code, but this is out of scope, you will need to do this research on your own (it's quite trivial once you get the hang of it).
c. use the native methods from the bridge inside your java app wherever you see fit.
A very good tip would be to go through a hello world sample of ndk :
http://www.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html
Enjoy.

Generate Java Heap Dump on uncaught Exception

I try to generate a Heap Dump when a uncaught exception is fired. I tried using jmap, but because the process is finished when the exception happens this is not possible.
Using a UncaughtExceptionHandler is no option either, because I only have the binaries of the programs that is executed.
Can anyone help me?
EDIT: It is important that the technique is available through a command line or similar, because I need to automated this. Using a GUI is no option
This can be achieved with JVMTI agent that will listen to VMDeath event and then use JMM interface to initiate Heap Dump.
Here is a sample source code of such JVMTI agent:
#include <jvmti.h>
#include <string.h>
#include <stdio.h>
#include "jmm.h"
JNIEXPORT void* JNICALL JVM_GetManagement(jint version);
void JNICALL VMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
JmmInterface* jmm = (JmmInterface*) JVM_GetManagement(JMM_VERSION_1_0);
if (jmm == NULL) {
printf("Sorry, JMM is not supported\n");
} else {
jstring path = (*jni)->NewStringUTF(jni, "dump.hprof");
jmm->DumpHeap0(jni, path, JNI_TRUE);
printf("Heap dumped\n");
}
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti;
(*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0);
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMDeath = VMDeath;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
return 0;
}
After you've compiled it into the shared library (libdump.so) run Java with -agentpath option:
java -agentpath:/path/to/libdump.so MainClass
If you wish to handle uncaught exceptions instead of waiting for VMDeath, you may use similar technique to install callback for Exception event. Look here for an example.
Try to put your processing into a deamon thread. this way you can access it with memory analysis tools. JVisualVM is a JDK tool you can find it in your JAVA_HOME\bin.
There are also another way, called dump analyser. You run your application with these JVM parameters :
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath="your_path"
But this is used only if you have an OutOfMemoryError. Try to find if it's possible to generate the dump for any performance.
Another good eclipse based tool is MemoryAnalyzer
I would like to suggest Java Visual VM. It can connect dynamically. I found it useful. You might want to give a try.

Determining whether STDERR is going to terminal

I have a suite of Java programs which are used as command-line tools on our Linux servers. Most of them use a class that prints a progress bar on STDERR, similar to Perl's Term::ProgressBar.
I'd like to have the progress bar shown whenever STDERR is going to the terminal and automatically disable itself when STDERR is redirected so that there aren't all sorts of progress bar pieces in the redirected data.
Checking System.console() == null was my first thought, but redirecting STDOUT is enough to make this true, even if STDERR is still going to the terminal. Is there anything I can check that is specific to STDERR? A solution that is Linux-specific or that uses native APIs would be ok for my needs.
I think what you're looking for is isatty(3), in unistd.h. There's no way to tell whether a file handle has been redirected, period, but that'll tell you whether it's still interactive. See the source for the tty command in GNU coreutils.
After combining #chrylis's pointer with this answer and doing a little tweaking, what I finally ended up with is:
create and compile Java class with native method signature
use javah to generate C header file
create .cpp file, implementing function with isatty
compile C++ code into shared library
run Java program, using -Djava.library.path=... to tell it where your custom library is
Java class:
package com.example.cli;
class LinuxTerminalSupport {
public native boolean isStderrVisible();
static {
System.loadLibrary("term");
}
}
ant target to generate .h:
<target name="generate-native-headers">
<javah destdir="native/" verbose="yes">
<classpath refid="compile.class.path"/>
<class name="com.example.cli.LinuxTerminalSupport" />
</javah>
</target>
.cpp file:
#include "com_example_cli_LinuxTerminalSupport.h"
#include "unistd.h"
using namespace std;
JNIEXPORT jboolean JNICALL Java_com_example_cli_LinuxTerminalSupport_isStderrVisible(JNIEnv * env, jobject obj) {
return isatty(fileno(stderr)) == 1;
}
Makefile (change java includes to reflect your $JAVA_HOME):
linux: LinuxTerminalSupport.o
g++ -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux \
-o libterm.so -shared -Wl,-soname,term.so LinuxTerminalSupport.o -lc
LinuxTerminalSupport.o: LinuxTerminalSupport.cpp
g++ -c -I/usr/java/jdk1.6.0_13/include -I/usr/java/jdk1.6.0_13/include/linux LinuxTerminalSupport.cpp

Categories