Strange AVC Denial

1,842 views
Skip to first unread message

Roman Mazur

unread,
Jul 12, 2016, 1:51:27 PM7/12/16
to android-porting
I'm working on a custom build based on Android 6.0.1 for Nexus 7. This custom build adds a special daemon that is started from init.rc and exposes some API to applications. Particularly, one of available methods creates a new file at /data/daemon_dir and returns a file descriptor making it possible to write to this file from an app.

The daemon has its own SELinux context (here it's named custom_daemon). And /data/daemon_dir has custom_daemon_file context. There are sepolicy rules that grant file creation to the daemon and file writes to untrusted_app.

The configuration described above worked on Android 5. But after merging with Android 6, I'm getting the following denial:

07-11 21:57:46.735 13389-13389/? W/Binder_2: type=1400 audit(0.0:945): avc: denied { write } for path="/data/daemon_dir/some_file" dev="mmcblk0p30" ino=496817 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:custom_daemon_file:s0 tclass=file permissive=0


Here are the rules that should allow the operation:

allow untrusted_app custom_daemon_file:file rw_file_perms;
allow untrusted_app custom_daemon_file:dir r_dir_perms;

allow custom_daemon custom_daemon_file:dir create_dir_perms;
allow custom_daemon custom_daemon_file:file create_file_perms;


An interesting thing in this denial report is that scontext is untrusted_app. But the denial is logged for the daemon process (13389 is one of its thread IDs and Binder_2 is a name of the binder thread that handles the API call).

I believe this mismatch is what is causing the denial but cannot understand why this happens and how this can be fixed.

Stephen Smalley

unread,
Jul 12, 2016, 4:32:06 PM7/12/16
to mazur...@gmail.com, android-porting, seandro...@tycho.nsa.gov
On 07/12/2016 11:57 AM, Roman Mazur wrote:
> I'm working on a custom build based on Android 6.0.1 for Nexus 7. This
> custom build adds a special daemon that is started from init.rc and
> exposes some API to applications. Particularly, one of available methods
> creates a new file at /data/daemon_dir and returns a file descriptor
> making it possible to write to this file from an app.
>
> The daemon has its own SELinux context (here it's named custom_daemon).
> And /data/daemon_dir has custom_daemon_file context. There are sepolicy
> rules that grant file creation to the daemon and file writes to
> untrusted_app.
>
> The configuration described above worked on Android 5. But after merging
> with Android 6, I'm getting the following denial:
>
> 07-11 21:57:46.735 13389-13389/? W/Binder_2: type=1400 audit(0.0:945):
> avc: denied { write } for path="/data/daemon_dir/some_file"
> dev="mmcblk0p30" ino=496817 scontext=u:r:untrusted_app:s0:c512,c768
> tcontext=u:object_r:custom_daemon_file:s0 tclass=file permissive=0
>
>
> Here are the rules that should allow the operation:
>
> allow untrusted_app custom_daemon_file:file rw_file_perms;
> allow untrusted_app custom_daemon_file:dir r_dir_perms;

(cc seandroid-list)

Assuming that you only want to allow apps to read and write files passed
to them explicitly by your daemon and not to directly open files in this
directory, you should only have:
allow untrusted_app custom_daemon_file:file { read write getattr };

In particular, you would not need to allow open permission to file nor
any permissions to the directory in this usage model, and not allowing
those permissions would be more secure as it would prevent apps from
directly accessing any of those files without going through your daemon.

> allow custom_daemon custom_daemon_file:dir create_dir_perms;
> allow custom_daemon custom_daemon_file:file create_file_perms;
>
>
> An interesting thing in this denial report is that scontext is
> untrusted_app. But the denial is logged for the daemon process (13389 is
> one of its thread IDs and Binder_2 is a name of the binder thread that
> handles the API call).
>
> I believe this mismatch is what is causing the denial but cannot
> understand why this happens and how this can be fixed.

No, the denial is caused by the fact that the app is running with
categories (c512,c768) and the file is not labeled with the same
categories. You can allow this by adding the mlstrustedobject attribute
to your type:
type custom_daemon_file, file_type, data_file_type, mlstrustedobject;

In 6.0, apps and their data files are assigned an automatically
generated category set (c512,c768 above) derived from their user ID in
order to isolate the processes and files of different users from each
other. This prevents cross-user or cross-profile access to /proc/pid
files and app data files, even if world-readable or -writable (sharing
is still possible by having the owning app open the file itself and pass
the file descriptor over binder or local socket IPC to another app, but
direct open is prohibited). This separation is currently applied to
untrusted apps and platform apps as a result of specifying
levelFrom=user in the seapp_contexts configuration.

With regard to the potentially misleading audit message, it is due to
the fact that this check occurs when your daemon tries to pass the open
file descriptor to the app, so it occurs while the daemon is the current
process. Before transferring the descriptor into the app's descriptor
table, SELinux checks whether the app is allowed to use it. So the
check is between the app's context and the file, but happens while the
daemon is still the current process.

Roman Mazur

unread,
Jul 13, 2016, 1:11:27 PM7/13/16
to Roberts, William C, Stephen Smalley, android-porting, seandro...@tycho.nsa.gov
>Assuming that you only want to allow apps to read and write files passed
>to them explicitly by your daemon and not to directly open files in this
directory, you should only have:
>allow untrusted_app custom_daemon_file:file { read write getattr };

Thanks, I missed that w_file_perms (and subsequently rw_file_perms) macros includes the open vector.


>No, the denial is caused by the fact that the app is running with
>categories (c512,c768) and the file is not labeled with the same
>categories. You can allow this by adding the mlstrustedobject attribute
>to your type:

Got it, thanks!
But speaking about the sharing scenario between apps, isn't it the same case I have with my daemon (when it opens a file descriptor and passes it to an app)? Why does it work for apps from different profiles/users?

And thanks for the clarification regarding the audit message.

>Wouldn't make more sense to make the daemon MLS aware and label these files with the category set of the requestor?

There are multiple apps that can access those files. And currently this access is granted using Android permissions model (the daemon checks if caller has the permission before opening a file). But my plan is to define a custom domain for these apps that will be assigned basing on application signature. And then use MLS to prevent sharing the files with other apps.
Would you point me to an example of an MLS aware daemon?

Thanks a lot for your help!

On Tue, 12 Jul 2016 at 22:20 Roberts, William C <william....@intel.com> wrote:
Wouldn't make more sense to make the daemon MLS aware and label these files with the category set
Of the requestor? This would prevent sharing the file with a different untrusted_app, unless that's
A possible part of your design. Granted, the service would need mlstrustedsubject to manage these,
but as long as you don't allow the service access to app_data_files (IIRC that's a neverallow) or other things
where MLS is used to further restrict access, then it should be ok.



>
> In 6.0, apps and their data files are assigned an automatically generated category
> set (c512,c768 above) derived from their user ID in order to isolate the processes
> and files of different users from each other. This prevents cross-user or cross-
> profile access to /proc/pid files and app data files, even if world-readable or -
> writable (sharing is still possible by having the owning app open the file itself and
> pass the file descriptor over binder or local socket IPC to another app, but direct
> open is prohibited).  This separation is currently applied to untrusted apps and
> platform apps as a result of specifying levelFrom=user in the seapp_contexts
> configuration.
>
> With regard to the potentially misleading audit message, it is due to the fact that
> this check occurs when your daemon tries to pass the open file descriptor to the
> app, so it occurs while the daemon is the current process.  Before transferring the
> descriptor into the app's descriptor table, SELinux checks whether the app is
> allowed to use it.  So the check is between the app's context and the file, but
> happens while the daemon is still the current process.
>
> _______________________________________________
> Seandroid-list mailing list
> Seandro...@tycho.nsa.gov
> To unsubscribe, send email to Seandroid-...@tycho.nsa.gov.
> To get help, send an email containing "help" to Seandroid-list-
> req...@tycho.nsa.gov.

Stephen Smalley

unread,
Jul 13, 2016, 1:11:27 PM7/13/16
to Roman Mazur, Roberts, William C, android-porting, seandro...@tycho.nsa.gov
On 07/13/2016 12:22 PM, Roman Mazur wrote:
>>No, the denial is caused by the fact that the app is running with
>>categories (c512,c768) and the file is not labeled with the same
>>categories. You can allow this by adding the mlstrustedobject attribute
>>to your type:
>
> Got it, thanks!
> But speaking about the sharing scenario between apps, isn't it the same
> case I have with my daemon (when it opens a file descriptor and passes
> it to an app)? Why does it work for apps from different profiles/users?

external/sepolicy/mls defines different constraints on app data files
versus other files. For app data files, which are labeled with the same
categories as the app process, we can impose a constraint on open that
requires equivalence and omit constraints on read and write, thereby
allowing passing and use of open file descriptors while blocking direct
open of any file that has a different category set. For other files, we
cannot do that without blocking any form of open to the file (even if
only for read access) since it will not have the same categories; we
instead use conventional MLS constraints on read and write, which will
generally allow read access and prohibit write access (unless the file
type is a mlstrustedobject).

>
> And thanks for the clarification regarding the audit message.
>
>>Wouldn't make more sense to make the daemon MLS aware and label these
> files with the category set of the requestor?
>
> There are multiple apps that can access those files. And currently this
> access is granted using Android permissions model (the daemon checks if
> caller has the permission before opening a file). But my plan is to
> define a custom domain for these apps that will be assigned basing on
> application signature. And then use MLS to prevent sharing the files
> with other apps.
> Would you point me to an example of an MLS aware daemon?

We generally would not create a MLS-aware daemon per se but instead just
a SELinux-aware daemon. Examples in AOSP today include the init
property service, servicemanager, keystore, debuggerd, and drmserver;
they fetch the security context of their client via getpeercon or
getpidcon, invoke SELinux permission checks via selinux_check_access,
and possibly manage or lookup object security contexts of their own.

Reply all
Reply to author
Forward
0 new messages