Why reading permission to /proc/1/maps is denied and why doesn't the denial appear in logcat?


Question

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!


Answer

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.


Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes