How does Android perform security checks on native code? Suppose we declare permission X in AndroidManifest.xml, does it mean we inherit that same permission X in our native code?
How does Android perform security checks?
There are basically two ways the permissions are enforced.
First of all on kernel level: each installed app is assigned a unique (linux) user id and each time your app is started Android will spawn a process and sets the user id of that process to whatever your app userid is. Now accessing e.g. the filesystem or certain hardware features like network is enforced by using the standard linux group permission system. E.g. access to network is only allowed for a network group and your app user is part of that group if you request the network permission in your manifest.
Security in userspace like accessing certain ContentProviders or sending broadcast messages and so on simply can't be relayed to the OS. So once you call a method from either Java or native code you can be (pretty) sure that there is some software check in the end that ensures that you can't do things you have no permission for. The NDK API will most probably simply call (maybe indirectly) some Java method so there is probably no need to have separate checks for native and Java code (but Idk exactly how that is done).
It is likely that you can circumvent some of the Java checks by using native code like networking on the UI thread should work (if you have the network permission). It is also possible that there are loopholes that can only be exploited by using native code but that should be rare. It should not matter in the end what type of code you use.
#user827992
the NDK just produce some digested machine code for the dalvik, there aren't API available in C/C++ for Android; you don't have a problem about using a particular set of API that requires a certain permission because you simply can't even code that and access the API in the first place.
Not true, native code written in C/C++ is at compile time of the app compiled in native machine code for the CPU and at runtime executed directly by the CPU, no dalvik involved. You get back to dalvik if you call some Java method via JNI (through the NDK API) though.
Also there is a lot of Android API available through the NDK, thats the reason it exists.
According to the "Android logic" there is no point to do that for at least 2 reasons:
you always need to code some java lines to make your app, so your entry point will always be the java language and your java app; you can't do an apk with only C/C++ code.
the NDK just produce some digested machine code for the dalvik, there aren't API available in C/C++ for Android; you don't have a problem about using a particular set of API that requires a certain permission because you simply can't even code that and access the API in the first place.
In the end just think about an android as a java application where you can code in C/C++ your own business logic for the heavy computational stuff, everything that Google provides you in terms of API and policy is supposed to be related only with the Java language.
Related
In android does the application built with c++ (and packages in apps Like Termux) run on top of the Dalvik JVM or directly communicate with the Linux Kernal
This is explained partly in the Concepts section of the Android NDK documentation.
In brief: every Android user application needs to run the Android event loop in some capacity to receive events, participate in the application lifecycle, and display stuff on the screen.
What people call "native" c++ applications are actually running a "hollow" Java Android application/activity on top of ART (the Android "Java" runtime). The native part is expected to do everything that you get for free from normal Java-based activities: pump events and update the screen regularly.
Now, to answer your final question: for some aspects they can use the Android kernel directly. However, this is a very limited set of operations and more interesting operations either require some of the native APIs (which use an RPC mechanism called Binder to talk to system services) or use JNI to talk to a Java implementation (that in turn probably still uses Binder).
I am implementing an Android ODM system. I would like to create a VirtualDisplay constructed around an ImageReader so that the process providing the virtual display will receive the series of frames coming out of SurfaceFlinger as HardwareBuffer instances.
The intention is to fetch out the Linux dmabuf handle to each received HardwareBuffer by using AHardwareBuffer_fromHardwareBuffer() to get the corresponding native object, then convert it to an EGLImage with eglCreateNativeClientBufferANDROID() and then finally use eglExportDMABUFImageMESA() to obtain the dmabuf filedescriptor.
The critical piece of API -- AHardwareBuffer_fromHardwareBuffer() -- lives in the native library called "libandroid". Google documentation (see https://source.android.com/devices/architecture/images/vndk_design_android_o.pdf) explicitly indicates that vendor programs are prohibited from using API in libandroid.
This seems strange, because libandroid is already exposed in the application NDK. I think this means that backward portability in all future Android releases is therefore already demanded of libandroid.
Is there any existing way that I can make my vendor program link against this API? If not, could AHardwareBuffer_fromHardwareBuffer() be migrated out to the VNDK in a similar way as some of the other native C++ API's related to AHardwareBuffer have been?
Updated:
It's a pre-installed service that needs (in addition to doing these VirtualDisplay and ImageReader mechanics) to do some interaction with a custom HAL (so: not anything that implements one of the standard Google HIDL interfaces) that my customer is implementing.
I think that relegates us to needing to pre-install into the /vendor partition, right? I don't know whether this technically speaking makes me a "VNDK process", but the restriction against linking against libandroid kicks in anytime that I put "vendor: true" into the Blueprint file.
This pre-installed service sits in the AOSP tree because I'd like to sign it with the platform key so that the service can set its android:persistent property in AndroidManifest.xml to avoid it being subject to arbitrary shutdown from ActivityManager.
Other pre-installed applications will go badly if this VirtualDisplay doesn't end get instantiated. I'm uncertain what this means for GSI. Maybe you're likely to say that, with a GSI image installed for testing, none of those other preinstalled apps are present either so there's no problem.
Is this process a regular application (APK that provides Activities, Services, etc.) that just happens to be pre-installed on the device? I'd imagine it is if you're using VirtualDisplay and ImageReader. If so, there should be no problem using libandroid.
The restriction on libandroid is specifically for VNDK processes, i.e. lower level parts of the system. The restriction is there because several things in libandroid depend on the Android Framework, ART runtime, etc. as well as unversioned and non-fixed internal interfaces to them. So the usual versioning of VNDK-available libraries, where literally vndk binaries from old versions of the OS must work on newer versions of the OS, doesn't work for libandroid because of those dependencies on non-stable internal interfaces.
But if you're writing something that sits above the framework and is only using public APIs, then it's not a VNDK process and those restrictions don't apply.
(Note: I work on Android and have been involved in AHardwareBuffer APIs. But I'm not a VNDK expert nor an expert on the rules around vendor processes and vendor-preinstalled applications. So take this as reflecting my own personal understanding, and not an official statement from the Android team: if there's official documentation that contradicts what I've said, it's probably right and I'm wrong.)
I want to call functions provided in com_android_bluetooth_hid.cpp in android source from my own app. Target Android versions are >=4.4 and <=5.x. I understand JNI, and can compile my own code and call from my own app.
Would it be possible to call android's library from my app? How
Also, to call functions in that specific cpp file, are BLUETOOTH and BLUETOOTH_ADMIN permissions sufficient or something else (other permission, or root) would be required?
The cleanest way to call Android's CPP code is, generally, copying the relevant pieces to your repository and building as part of your app. Following this approach, your app will only call the public APIs - either Java or C/C++.
But this may not be relevant in cases when this code must run with special permissions, as system service, like mediaserver or Bluetooth stack.
I am afraid that the code you wish to run belongs to this second category, therefore none of the available tricks will not help.
On the other hand, a custom ROM may be a solution you are looking for. It may happen that you don't need to forge a full system. It may be enough to use a rooted device and replace the bluetooth service with your custom one.
I would still advise you to provide the missing callbacks for the service, instead of calling the functions directly from your app: you better not mix contexts between a user-space app and system service.
Now wait just one moment before you mark this as a duplicate, because this is a very specific question.
I'm not asking if you can write an application using another language which is a binding using the NDK; what I want to know is:
At a hardware level, how does dalvik interact with the Linux kernel on android devices?
The answer to (1) as I understand it, is that because android is fundamentally a Linux system, this is done via syscalls. Which is to say, at some level the davlik/art VM must interact with the C Linux kernel through a C API.
If you had root permission on a device, why could you not do the same thing from a native system binary?
So, certainly it would be a painful experience, but technically is there any reason why it would not be possible to write an application purely in C, without using the android run-time at all?
(Note: Not without the run-time; obviously the run-time must be present to do various things like device initialization; but a stand alone binary that did not interact with the run-time).
(I can think of a few reasons why this might be the case, specifically the run-time requiring exclusive hardware access to various hardware, but I can't find any specific documentation about it)
It is possible, this is how daemons work on Android (think RILD for example). However you cannot gain access to the Android facilities (graphics, location, etc) as there is no API from C.
Note that in order to speak to the Android API, your process needs to be a child of zygote. If you spawn a process from an ADB shell, or from init you will not be a fork() of zygote and will not have direct access to the JVM.
I want to access Android API classes outside an Android project. For example is it possible to get an object to the Context of the device connected to a machine or the running emulator?
This will allow access to a system services like PowerManager or ActivityManager outside an Android device. If not via Context object, is there any other way to access the system services for a device/avd outside Android?
No way. Distributed android API classes are merely stubs good enough to compile against them.
Even most innocent stuff is stubbed out to throw RuntimeException on invocation. If you like to know status of the system, you will have to use SDK tools. Or write app exposing android objects via some remote access technology
I very much doubt that it is possible. The distributed SDK classes do not include many parts of the internal API. See, for example, this thread. Besides, what use would there be to have a system service object like PowerManager without a system (or an emulation of one) to back it up?
It sounds like what you're trying to do is not really access things on the device, as much as remotely control the device. In this case, there are some external tools that you should look into. The tools are mainly focused on testing, and are based on instrumentation for apps. You can look at robotium and monkeyrunner, to start with, as they provide a bit of functionality that might help you accomplish what you want. Other than that, you can also do what those tools do and write an app which listens for intents from adb, performs actions based on those intents, etc..., but you'll obviously be doing a lot of communication at a high level, so this might not be the most efficient (and I'm not sure how you'd transfer much data, which would be required for real RPC, which it sounds like you want to do).