2

I'm developing a native app for Android, and I'm occasionally confronted with permission denied which doesn't trigger a log in the logcat logs. For example, trying to run:

shell@kltevzw:/ $ cat /proc/<some-not-shell-pid>/maps
/system/bin/sh: cat: /proc/<some-not-shell-pid>/maps: Permission denied

from the adb shell prompt results in a permission denied message sent to stderr, but nothing appears in the logcat. It's not a unix permissions problem as well, as anyone should be able to read the file. For example:

shell@kltevzw:/ $ ls -lZ /proc/1/maps
-r--r--r-- root     root              u:r:init:s0 maps

It happens in some other situations as well, in which I have less control of the environment. Is it possible that this is caused by some dontaudit rules in the policy? I ran sesearch --dontaudit /sepolicy but didn't find there any relevant rules. Does anyone here know why are some denials sent to the log and some don't, and how to debug such cases?

Thanks!

4

REASON 1:

Apart from traditional Discretionary Access Control (DAC), - that makes use of *NIX owner/group/mode of processes/files to allow/deny access - Android implements several other access control mechanisms of Linux kernel to make itself more secure, such as Seccomp Filter was implemented in Oreo.

REASON 2:

While DAC is allowed by-default, SELinux (a Mandatory Access Control) works in denied by-default mode. Any access attempt that isn't explicitly allowed in an SE Policy rule will be denied. Using same, access to /procfs has been tightened in Android O which won't let a non-privileged process/user read - e.g. - /proc/stat and /proc/filesystem. Same restricts you from reading /proc/1 when running as a non-root user from your app.

If SELinux on your device isn't Enforcing, you should be able to read /proc/1 but there are some other security restrictions which - unlike DAC and MAC - are specific to /proc pseudo filesystem.

REASON 3:

Android by-default mounts /proc with hidepid=2,gid=3009 options, which means a non-privileged user will be able to view only its own processes (running with same UID) (ref). So your app won't be able to see directory /proc/1. The only exception is the processes which are member of group AID_READPROC (GID 3009).

REASON 4:

But still if you (re-)mount /proc without option hidepid, you won't be able to read /proc/1/maps because Linux kernel only permits processes having capability SYS_PTRACE to read the details of currently mapped memory regions.

An example of working non-root process on Android is incidentd that runs with CAP_SYS_PTRACE as well as a member of group READPROC. Also the SE Policy rule like following should be defined to allow access:

allow incidentd init : file { read getattr open }

LOGGING:

As far as logging of permission denials is concerned, logd (the service from which logcat reads) is an Android specific logging daemon which necessarily logs events from within Android's native and Java framework (such as manifest permission denials), but optionally includes kernel events (which we can also see using native command line tool dmesg). SELinux denials are also logged to kernel log:

$ ls /proc/1
ls: cannot access '/proc/1': Permission denied

# dmesg | grep avc
[37914.650314] type=1400 audit(1548757064.171:33323): avc: denied { getattr } for pid=28576 comm="ls" path="/proc/1" dev="proc" ino=803674 scontext=u:r:untrusted_app_27:s0:c512,c768 tcontext=u:r:init:s0 tclass=dir permissive=0

# logcat | grep avc
01-29 14:17:44.171 28576 28576 W ls      : type=1400 audit(0.0:33323): avc: denied { getattr } for path="/proc/1" dev="proc" ino=803674 scontext=u:r:untrusted_app_27:s0:c512,c768 tcontext=u:r:init:s0 tclass=dir permissive=0

However Linux kernel may or may not log all of its internal permission denials depending on multiple build and runtime configurations including printk loglevel, DYNAMIC_DEBUG and/or others I'm not sure of. Therefore such messages may not appear in logs.

If you want to get logs related to security events, you can make use of Linux kernel's Auditing System. For that you need to use auditctl tool for defining rules (root required), and you would get details about the denials in logs through dmesg or logcat. Fo more details on how to define rules, see this answer.

PS:

Another reason of not being able to access a certain PID in procfs is PID namespace that isn't relevant on Android so far but very common for isolation mechanisms like containers. In a new PID namespace, any process from parent namespace isn't visible and a process could have same PID (including PID 1; init) as that of some other process in some other PID namespace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.