I come from a C/C++ background and now do a lot of C# stuff.
Lately I have become interested in doing some projects in Java since playing around with the Android SDK.
I know that Java apps run in a sandbox that can limit their access to the system.
In a desktop/server application environment what kind of things are restricted?
Java applications are much in a sandbox as .NET applications are in a sandbox. They both run on their respective virtual machines, and do have some limitations as to what they can do, but for the most part, they have a good deal of access to the system, including access to native code through certain calls.
You may be thinking about Java applets, which run inside a browser, and generally will be in a security sandbox that prevents access to the system resources such as local files. (This restriction can be circumvented by specifically granting access to the system to certain applets.)
Here's a section on Security Restrictions for applets from The Java Tutorials, which includes a list of restrictions placed on applets.
Typically desktop and server application run with security disabled. However, Java and the JVM still have a robust type system, so you can't for instance cast to types that an object was not created with, cannot access freed memory and can't run off the end of buffers.
For normal desktop and server apps, the limitations are not related to the sandbox concept (though you could use it to apply very fine-grained restrictions to e.g. user-submitted code) but to the platform-independant nature of Java. Basically, OS-specific stuff and hardware access usually can't be done in pure JAVA unless specifically adressed by the API library.
Examples are:
Windows registry
Windows system tray
Bluetooth
WLAN configuration
I think the main limitation you might see, is the ability to easily use the native system API's if you needed, for example if you needed to use a user32 or kernel32 API from java I think it is possible, however it is not an easy task to do, however in C# it is fairly easy thing to do.
Also if you have some legacy C/C++ dll's you can still use them in a C# application, while in java is still hard to do especially that in the worst case when your native code api has to use pointers, you can use unsafe mode in C# application to pass pointers and allocate fixed memory on stack ... etc.
but as mentioned above Java & C# in general are very much have the same limitations especially if you are targetting being platfrom independent.
Related
I come from a C/Linux background and don't have much background in Java. I generally develop system administrator utilities like :
disk cleanup
retrieve lost data / files
repairing file systems
disk de-fragmentation
I also develop Network monitoring security applications which help admins monitor :
- their networks,
- scan incoming & outgoing data packets,
- remotely block ports / USBs
- monitor emails with attachments etc
Right now we write code in C for Linux which has to be ported to windows but such a problem will not exist in Java.
My questions are :
Is Java the right language for writing these applications & utilities (as mentioned above)?
I understand Java will provide Libraries and classes to access system resources / network / sockets but will Java abstraction be a hindrance at some point (which would restrict the flexibility which C/C++ provide )?
If for example I want to write a utility to repair a file system / or retrieve data for Windows & Unix ...will I be using same API for both OS or there are different API for different OS?
I am not concerned about the speed / execution trade off since none of my applications have to make real time decisions as in the gaming industry.
Java is the right language if you want portability. You can do almost everything you can do with C/C++ and you can utilize patterns and libraries that help you create great maintainable designs. In case there is something very low level you cannot do with Java, you always can create your own native code that is loaded with Java Native Interface. Thus the only non-portable code you will have will be these native-code libraries.
Right now we write code in C for Linux which has to be ported to
windows but such a problem will not exist in Java.
Java can abstract away only so much since in the end, low level stuff always boils down to making system calls, which are different between OSes.
As long as you're working with pure java logic, or simple operating system utilities, you'll be golden. You want to open a TCP socket and connect to google.com? No problem. You want to open a file in a known location, read some lines, process them, and write the results to a different file? No problem, Java has you covered.
But, if you want to do more low-level stuff with Java, you'll run into trouble pretty soon. You want to open a raw socket and send a TCP packet? You can't, windows doesn't allow that. You want to get a file's creation time on Linux? You can't, Linux doesn't keep that information. Java's BasicFileAttributes.creationTime() will return a file's modification time on Linux. You want to get a nanosecond resolution timestamp? Well, you can, but only on some OSes. Or say you want to get the computer's hostname without resorting to a network lookup (which depends on a network being actually available), well, get ready for some hacking (this is my own answer by the way).
Now, to your more specific questions:
Is Java the right language for writing these applications & utilities (as mentioned above)?
I frankly don't know. I never tried defragmenting or restoring a file programmatically from Java. But since it involves some very low level filesystem operations, I suggest you do some serious reading before moving to Java. Check whether the APIs you need exist in the language itself or in some good libraries.
I understand Java will provide Libraries and classes to access system
resources / network / sockets but will Java abstraction be a hindrance
at some point (which would restrict the flexibility which C/C++
provide )?
Yes. For instance, it's impossible to open a raw socket using pure Java. And if I recall correctly, it's also impossible to set some socket options.
If for example I want to write a utility to repair a file system / or
retrieve data for Windows & Unix ...will I be using same API for both
OS or there are different API for different OS?
I never tried repairing a file system in Java, so I can't tell you about the APIs involved. But I find it hard to believe you'll find a pure Java api for doing low level stuff with the file system. You'll probably have to write your own native code (and run it through JNI) or use someone else's library (which probably uses JNI, like the raw socket library I mentioned earlier).
I am planning to create a software that will be compatible with both Windows CE and Android devices.
Nothing has been decided yet, but so far I've imagined that I could write most parts of the program using C++ code that could be reused on these two platforms, except for system-dependant things like threads. C++ is highly recommended for performance in my case.
In the case of system-dependent things I would create interfaces that would be implemented in two different ways, one using the win32 API, and the other one using the linux equivalent. The other parts of the code the logic) would be independent and reused on both platforms.
The only part of the application that would not be written in C++ would be the user interface. Using the Android API on Android platforms, and something else on Windows CE (C#, Java, don't know yet).
I've read that Android is not like other linux distributions because many linux features are not available from native code on it.
So my question is : is it possible to natively create and use sockets, threads, critical sections (and any other system-dependant things) from a native linux api using JNI (i.e the equivalent of the win32 api but for linux) or do i always have to create them into the Java layer and pass them down to the native code ?
I've not yet decided how II am going to build this, i'm just informing myself on the different possibilities.
Thank you.
NDK implemented POSIX (include pthread, mutex) and BSD socket, so you don't necessary create them with java objects.
However, STL support is still crappy IMO, which you may need to pay attention with your own code or porting any dependency libraries.
It is possible to do all of this with JNI, but I would think twice before doing so. Using JNI has its share of liabilities; it will make development and debugging considerably more difficult. You will also end up with a lot of callbacks to Java code to communicate with the GUI. Think of features like visual progress indicators for ongoing operations. And don't forget that in the end, your app's performance may suffer because of the extra indirection required by each JNI call. Be sure to measure performance in either case. JNI, or C++ for that matter, does not automatically make anything faster.
Also, it may be harder than what you think to just "mirror" your app on another operating system. Android, as an operating system, behaves differently not only on the GUI side (it is, for example, nonsense to provide a back button within in an Android app), but also on the inside, with its typical app architecture broken down into Services, Activities and Receivers. It's not just "a different GUI", not at all.
If you have backend functionality that really can and should behave identically on both platforms, then go on, write it in C++ and reuse it on Android via JNI. But it may be easier, and it may be equally or more performant, to just implement it or parts of it from scratch on Android, using Java. Without knowing any details about your project, it is impossible to say.
Why don't you try and implement a simple test app on Android using JNI? Try to use the NDK to send an HTTP request in a background thread and write the respone back to Java as a String. You'll eventually see that it works, but you will also have a better understanding of the difficulties involved.
This might be a silly question. I am in the process of writing a website. I have already weighed the benifits of using C/C++ in this java program, though every thing i am going to do using C can be implemented in java(Not easily). This code would be written as an applet to be run on the website. I would like to know if anyone could tell me if jni works across different os'es in an applet, and what complications could using jni in an applet pose?
IMO, this is a bad idea. (And this applies to using all forms of native code library in applets, not just JNI libraries.)
First complication is that this can only possibly work in a trusted applet. And (frankly) if a user says "OK" to dialog that asks if your applet should be trusted / run, they are probably making a big mistake. (Potentially nasty applets + potentially nasty native libraries == BIG RISK!)
Second complication is that you need to write, build, test, etcetera a different version of the native library for each and every combination of hardware AND OS platform you want your website to support. If you don't, your website won't work for some of your users.
If you have a corporate user base with a mandated COE and established trust relationships (e.g. preinstalled corporate certificates) these problems are more manageable, but there is still an issue in both cases.
Related:
Dynamically loading a native library inside Java applet
I am curious about what automatic methods may be used to determine if a Java app running on a Windows or PC is malware. (I don't really even know what exploits are available to such an app. Is there someplace I can learn about the risks?) If I have the source code, are there specific packages or classes that could be used more harmfully than others? Perhaps they could suggest malware?
Update: Thanks for the replies. I was interested in knowing if this would be possible, and it basically sounds totally infeasible. Good to know.
If it's not even possible to automatically determine whether a program terminates, I don't think you'll get much leverage in automatically determining whether an app does "naughty stuff".
Part of the problem of course is defining what constitutes malware, but the majority is simply that deducing proofs about the behaviour of other programs is surprisingly difficult/impossible. You may have some luck spotting particular patterns, but on the whole you can't be confident (and I suspect it's provably impossible) that you've caught all possible attack vectors.
And in the general sphere, catching 95% of vectors isn't really worthwhile when the attackers simply concentrate on the remaining 5%.
Well, there's always the fundamental philosophical question: what is a malware? It's code that was intended to do damage, or at least code that doesn't do what it claims to. How do you plan to judge intent based on libraries it uses?
Having said that, if you at least roughly know what the program is supposed to do, you can indeed find suspicious packages, things the program wouldn't normally need to access. Like network connections when the program is meant to run as a desktop app. But then the network connection could just be part of an autoupdate feature. (Is autoupdate itself a malware? Sometimes it feels like it is.)
Another indicator is if a program that ostensibly doesn't need any special privileges, refuses to run in a sandbox. And the biggest threat is if it tries to load a native library when it shouldn't need one.
But all these only make sense if you know what the code is supposed to do. An antivirus package might use very similar techniques to viruses, the only difference is what's on the label.
Here is a general outline for how you can bound the possible actions your java application can take. Basically you are testing to see if the java application is 'inert' (can't take harmful actions) and thus it probably not mallware.
This won't necessarily tell you mallware or not, as others have pointed out. The app could still do annoying things like pop-up windows. Perhaps the best indication, is to see if the application is digitally signed by an author you trust; if not -- be afraid.
You can disassemble the class files to determine which Java APIs the application uses; you are looking for points where the java app uses the OS. Since java uses a virtual machine, there are well defined points where a java application could take potentially harmful actions -- these are the 'gateways' to various OS calls (for example opening a socket or reading a file).
Its difficult to enumerate all the APIs, different functions which execute the same OS action should require the same Permission. But java's docs don't provide an exhaustive list.
Does the java app use any native libraries -- if so its a big red flag.
The JVM does not offer the ability to run arbitrary code, or use native system APIs; in particular it does not offer the ability to modify the registry (a typical action of PC mallware). The only way a java application can do this is via native libraries. Typically there is no need for a normal application written in java to use native code (unless it needs to use devices).
Check for System.loadLibrary() or System.load() or Runtime.loadLibrary() or Runtime.load(). This is how the VM loads native libraries.
Does it use the network or file system?
Look for use of java.io, java.net.
Does it make system calls (via Runtime.exec())
You can check for the use of java.lang.Runtime.exec() or ProcessBuilder.exec().
Does it try to control the keyboard / mouse?
You could also run the application in a restricted policy JVM (the instructions/tools for doing this are not as simple as they should be) and see what fails (see Oracle's security tutorial) -- note that disassembly is the only way to be sure, just because the app doesn't do anything harmful once, doesn't mean it won't in the future.
This definitely is not easy, and I was surprised to find how many places one needs to look at (for example several java functions load native libraries, not just one).
How does Google App Engine sandbox work?
What would I have to do to create my own such sandbox (to safely allow my clients to run their apps on my engine without giving them the ability to format my disk drive)? Is it just class loader magic, byte manipulation or something?
You would probably need a combination of a restrictive classloader and a thorough understanding of the Java Security Architecture. You would probably run your JVM with a very strict SecurityManager specified.
In the Java case, I think it's mostly done by restricting the available libraries. Since Java doesn't have pointer concept, and you can't upload natively compiled code (only JVM bytecode), you can't break out of the sandbox. Add some tight process scheduling, and you're done!
I guess The hardest part is to pick the libraries, to make it useful while staying safe.
In the Python case, they had to modify the VM itself, because it wasn't designed with safety in mind. Fortunately, they have Guido himself to do it.
to safely allow my clients to run their apps on my engine without giving them the ability to format my disk drive
This can be easily achieved using the Java Security Manager. Refer this answer for an example.