I'm having trobule trying to create a custom file access logger for Android. I've check FileObsever but I need to get the PID (USERID would be useful also) of the process that had access to a certain list of files.
I've also tried different options but with no success.
Is is possible to log with PID accessed certain file?
Regards!
There's been some discussion of adding PID reporting to the Linux inotify() mechanism (which is what FileObserver is presumably based on), but I'm not finding out from initial searches if that was actually merged and thus inherited by Android - and if it was, it would likely only work for foreign UID's for a monitor with administrative privileges.
You could try the FileObserver and then immitate lsof by scanning through /proc for fd's, to whatever (limited?) extent you'd be allowed to do so on Android. This would however give you race condition issues - the file could be closed again before you saw "who done it".
Likely if you really want to do this, you'll need a custom ROM - you could apply any necessary patches to inotify and either bless your security app with permissions or (if you prefer to be that way) disable the permission checks on reporting.
What I found about the patch - current merge status unknown:
http://lwn.net/Articles/307536/
Intro to direct use of inotify() (without the PID reporting):
http://www.linuxjournal.com/article/8478?page=0,0
Related
I am trying to diagnose an issue in an app I have written. The issue is a sporadic one, and occurs only under real-world conditions: in the field, away from my PC, and when I’m in the middle of something else, with no resources to spare for immediate debugging. Therefore, my best bet is collecting and analyzing log data.
Unfortunately, by the time I realize the issue has struck again and get around to debugging it, any log data has already rotated out of the Android log as I frequently have other chatty apps running at the same time. Increasing the size of the log buffer has not helped (either Android does not honor it or other apps are still too chatty) so I have abandoned this route.
For this reason, I am now considering having my app log to a separate text file in addition to the regular log.
Now I could easily double every call like
Log.i(TAG, "something happened");
adding another call that writes the same thing to the log file—but that does not seem very elegant to me.
Another option would be to replace all calls to Log with a wrapper that writes the event both to the Android log and the log file.
Question: Does the Android API provide a built-in mechanism for this, i.e. telling Log to write its data to the default log and a text file at the same time? Or do I need to code this by myself?
Edit:
Assumptions:
I know where in my code I need to generate log output (which can happen anywhere, which may or may not involve an exception) and what I want to be written to the log.
Getting log data from the device to my PC is also not a concern (one-man show, I just plug my phone into my PC and transfer the log file).
If you know the current Android API has no built-in mechanism to achieve what I want, then ”no, Android does not support this” is a perfectly acceptable answer. In that case the solution is clear—I would fall back to the wrapper function. I am specifically not looking for a different approach to the problem.
After doing some more research, it seems the Android API does not provide a standard way to do this. There are two possible workarounds:
Mirror output at the source
System.out and System.err output, which is written to the console in desktop systems, writes to the log on Android. These two can be redirected into any PrintStream of your choice, which would give you all Java console output. You can subclass PrintStream to duplicate its input, feeding it into the default stream as well as into a file of your choice.
Create a class which exposes the same methods as android.util.Log. In each method, call through to the respective android.util.Log method and additionally log the data to a file. If you call your class Log (but with a different package name, e.g. org.example.Log), then all you need to do is replace imports of android.util.Log with an import of your class, and any Log method calls will go to your class.
Caveats: This will only give you data explicitly logged by your code (i.e. for which you have the source files), as well as anything that goes to System.out or System.err. It will not include log output from JAR libraries (if you cannot modify their source code), nor any output generated by the system (such as stack traces from default exception handlers) or by other processes (some of which may be system processes and report conditions related to your process).
Read the logs from the command line
This article explains how to read the logs from within Android. In a nutshell:
Android includes a command line utility called logcat on the device, which will give you a continuous feed of log messages until stopped. (Try it by adb shelling into your device and running it. It has a bunch of command-line options to control its behavior. Not sure if it is present on all distributions, though.)
Launch this command via Runtime.getRuntime().exec("logcat"), then obtain the input stream of the process returned. This will give you an input stream of log messages.
According to the article, your app needs the android.permission.READ_LOGS permission to read logs.
I have read statements that certain versions of Android (4.2 was mentioned) do not allow this permission to be granted to non-system apps, though. According to my own tests, behavior without this permissions differ: Anbox will return the full logcat, while LineageOS (tested on 15.1) will only show log entries from the app which called it (including previous instances, presumably everything associated with the same Linux user). This can be a limitation or a welcome filter feature. YMMV.
logcat conveniently has a command line option, -f, to specify an output file. I tried
Runtime.getRuntime().exec("logcat -f " + absolutePathToLogFile);
and logcat keeps logging as long as the app’s process runs. Killing the app (by clicking the X in the title bar on Anbox) apparently also terminated the child process.
Now you can either run this code when your app starts up, or you can turn this functionality into a separate app which starts on boot and continuously collects logs for all apps.
Caveats: This may fill up your storage space quickly if you have some chatty apps running (which is why entries rotate out of the logcat so quickly in the first place). It is recommended to make log mirroring configurable (e.g. via Preferences) and/or ensure old files are deleted regularly. Also, if you keep the logcat process running until your app terminates, you will not be able to access the file over MTP as there is no easy way to run the media scanner (if you scan the file while it is still written to, it will appear truncated over MTP until another media scan runs).
You have not specified if some exception are thrown but you don't handle.
In case, take a look at this answer:
Android Handling Unhandled Exception
If you must look at a bunch of variables and objects, I'd suggest two choices:
Write a copy of your logs on a file. When your problem occurs, just ask the user to send the file to you. This is ideal during tests with self-aware users.
Obtain statistics about usage, like commercial software do. Just log user operations and send the data to your server (you would need one for this). This is the most transparent way to do remote logging.
In the case of writing log to a file, you can read and write what you want in internal memory (inside the app's sandbox) or external memory (in this case, write permission is required and explicit permission must have been granted at runtime if you are targeting Android 6 and above).
I had earlier written a standalone daemon to access a custom device (/dev/mydev0). Looking at AOSP source, I figured I needed setup policies in following files to make it work:
new file device.te containing:
type mydev_device, dev_type;
new file mydevsrvc.te containing
# service flash_recovery in init.rc
type mydevsrvc_type, domain;
type mydevsrvc_type_exec, exec_type, file_type;
init_daemon_domain(mydevsrvc_type)
allow mydevsrvc_type mydev_device:chr_file rw_file_perms;
edited file_contexts to add:
/dev/mydev[0-9]* u:object_r:mydev_device:s0
edited service_contexts to add:
mydevsrvc u:object_r:mydevsrvc_type:s0
And started the daemon by editing init.flo.rc to include these lines:
service mydevsrvc /system/bin/mydevsrvc
class main
user system
group system
seclabel u:r:mydevsrvc_type:s0
oneshot
Now, I need to access the device in android apps, so I must change the daemon into an android system service.
I can startup the service (thread) using BOOT_COMPLETED intent as explained in a previous question
I am not able to figure out how to setup SELinux policies so that this java service is also able to access the dev file.
[Update] I have continued using privileged daemon for this purpose. My java service connects to daemon through sockets. I don't have a better solution.
I finally figured out the answer. Posting it here, because there sure will be SEPolicy noobs like me looking for similar answers.
For this work, I needed to be able to access my device file from my java app that implements my service.
I needed to add following rule in my sepolicy directory, in a new file:
allow system_app mydev_device:chr_file rw_file_perms;
Also, needed to make my service app run in system_app domain. For this, I need to:
Install in priv_app during Android build.
Sign it with platform key
Declare shared user id in manifest: android.uid.system. I found that without this, app runs in platform-app domain and wasn't able to access my device file even with corresponding change in SEPolicy rule. Not sure why though, I didn't bother to debug.
It might also be possible to run my Service app in mydevsrvc_type domain. I didn't find out how to do that, or whether that will work.
Here is a brief summary of the steps needed to implement SELinux on your Android device:
Add SELinux support in the kernel and configuration.
Grant each service (process or daemon) started from init its own domain.
Identify these services by:
Reviewing the init..rc file and finding all services.
Examining warnings of the form init: Warning! Service name needs a SELinux domain defined; please fix! in dmesg output.
Checking ps -Z | grep init output to see which services are running in the init domain.
Label all new processes, drivers, sockets, etc. All objects need to be labeled properly to ensure they interact properly with the policies you apply. See the labels used in AOSP for examples to follow in label name creation.
Institute security policies that fully cover all labels and restrict permissions to their absolute minimum.
Ideally, OEMs start with the policies in the AOSP and then build upon them for their own customizations.
for more https://source.android.com/security/selinux/implement.html
In response of your question to start service from init rc
you can just write one rc file like below. Where it will start your service on receiving of boot_completed
on property:sys.boot_completed=1
start mydevsrvc
for reference http://androidxref.com/9.0.0_r3/xref/device/generic/qemu/init.ranchu.rc#60
Possibly add a line in your ueventd.rc file or project specific to give the permission
I trying some stuffs with android as i am learning android development, now i have a scenario here.
I want to change the android phone's system date through my application( first i would like to know is this doable? )
Layout is as below
Now what i want is when the user clicks the button the date should increase by say 20 days
how can i do this.
i am unable to start...please help
As I already said that's impossible. You need the SET_TIME permission and that permission is granted by system only to applications that are in the Android system image. If You are able to gain that privilege you can easily change with the AlarmManager. SystemClock.setCurrentTimeMillis write the /dev/allarm file
adb shell ls -l /dev/alarm
crw-rw-r-- system radio 10, 46 2013-06-12 10:46 alarm
c stays for Character special file (stored in /dev).
system is the owner of the file
radio is the group
system and radio have read and write permissions (rw-, tree bits, int value 6), the others have only the read permission (r, int value 4). So the file permission is 664. If you can get root user (running su), you can change the permission of this file and wrote in it a new value. A bug report has been filled in order to ask google to allow apps to modify programmatically the mobile date but it has been declied. Here the reference
On Android, the only way for an application do have write access to the time&date is to get the SET_TIME permission, which is only possible for "applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission." (see signatureOrSystem protection level).
The only way for your application to reach this protection level is to run on a rooted device, or build and sign your own android rom.
If this is your case, you can easily use the AlarmManager or simply the Calendar instance.
Good luck!
Normal user applications does not have permission to change the device time. Read the answer by cashbash in the following post for the alternate option.
Unfortunately, blackbelt is right; android lets us do a lot of cool things, but changing system time programmatically is not one of them.
Since I see that you are looking for more credible/official sources, I suggest you check out this open ticket with Google, which suggests this is an open problem--it ought to work, but doesn't, and it doesn't seem Google is going to fix it anytime soon. The gist of it is that the SET_TIME protection level is set higher than it ought to be. (for more information on permissions, see here)
Although this is not quite the same as changing the time programmatically, you can still make the user change the system time for you if for some reason you do need system time to be changed. This thread will explain how to go about implementing that if you want to go that route.
Hope this was helpful information!
This question has been asked before at How does Android enforce permissions?. While the discussions there are good, the question is still not fully answered.
In the development environment, exceptions are thrown when the app tries to do something that requires permissions not declared in AndroidManifest.xml. So how does the run-time system implement the run-time checking?
I guess it's most likely done in the core framework, which may or may not need support from native code. But I don't know what source code files in AOSP are relevant to this.
Android uses a lot of the standard Linux(-kernel?) mechanisms especially when it comes to hardware restrictions.
Every app gets assigned a new unique (Linux-)user id and whenever the app process is created the system creates it with that user id. The id will never change unless you remove the app. That means for accessing the lower system levels your app will appear as a certain user and every (Linux-)permission system that works with users will also apply to your app.
If you request WRITE_EXTERNAL_STORAGE in the manifest your app will also become member of the (Linux-)group (called sdcard_rw) that has permissions to write to that storage. Permissions on the filesystem are enforced to only allow writing to the system user (=owner) and the sdcard_rw group, anyone else (=other) may only read. See also Is Google blocking apps writing to SD cards
By doing that Android has to do pretty much nothing except for setting the correct UID/GIDs of the processes it spawns once the app starts and the rest is handled at lower levels. Apps that are not member of a certain group simply don't get access to certain hardware.
List of permission <> group mappings: platform.xml
There are also some (Android software) restrictions that are based on either the signature of your app and / or simply by looking up the permissions your app requested: e.g. ContextImpl#checkPermission() - but those permissions have to be checked at every entrypoint to code that allows restricted actions.
From time to time people discover ways to e.g. turn on GPS programmatically because a check like that is missing somewhere.
With regard to your second paragraph, "exceptions" are runtime faults. Permissions are not enforced at build time, only at run time.
Accessing hardware, low level operating system resources, and system files generally requires the app userid to be a member of an appropriate group which it may be assigned by the package manager as a result of having a corresponding android permission. (Familiar examples of that would be network sockets, and the sdcard write which zapl mentioned, but also system-only things like talking directly to the GSM modem or reading the raw touchscreen coordinates).
For the majority of android operations that are done by way of calling library functions which are stubs for interprocess communication to services running in a different process, the platform code running in the more privileged process on the receiving end of the ipc request checks with the package manager to find out if the calling application has the necessary android permission.
Many special permissions are only available to apps signed with the system signature - even if another app claims those in its manifest, they will not be applied by the package manager.
I'm new in Android. I have an Idea to enrich user's knowledge whilst installing a desired application.
the idea is developing an application that can analyze .apk file of the application to check if it's over-privileged or not. and inform the user if this application which he's trying to install is over-privileged or not.
but since there's already a mechanism from Android which asks user's consent to grant whatever permission the application requests, I'm not sure if my application can somehow intervene this mechanism, postpone it, pause it or it can not.
I'm not sure if my application can somehow intervene this mechanism, postpone it, pause it
None of these are possible, sorry. You are welcome to create your own custom firmware that has this feature, but you cannot create this capability via an SDK application, for obvious security reasons.
I am not far from where you are ~ the entire mechanization you seek is based on an xml file in the "root" of the installation - it is called AndroidManifest.xml = all permission based issues should begin original first efforts on that file:
The AndroidManifest.xml File
Every application must have an AndroidManifest.xml file (with precisely that name) in its root directory. The manifest presents essential information about the application to the Android system, information the system must have before it can run any of the application's code. Among other things, the manifest does the following: .....
the "app-store" web based distribution system is supposed to pick that up and not only make some decisions on what to present to the user but as well differentiate to some extent what to do in the matter but as I just got a Droid-X emulator available in my installation I can tell you for a fact that "versioning" is subject to oversimplification as we cannot rely on users being tech-geeks