Search code examples
androidsocketsjava-native-interfacenativeandroid-permissions

local socket access denied in api23, working in api21


I have an application and a service that are connected by local socket on the native level (C++/JNI). Both were built using target API level 21 and were working fine for years. Recently I have upgraded them to API level 23 and now I am constantly getting this error:

10-31 10:07:37.413 5760-5760/com.mycompany.myservice W/pool-151-thread: type=1400 audit(0.0:47942): avc: denied { connectto } for path=00494E554445565F4C4F43414C5F534F434B45545F53455256455200 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=unix_stream_socket permissive=0
10-31 10:17:44.373 4221-4221/com.mycompany.myapp W/pool-1-thread-1: type=1400 audit(0.0:72703): avc: denied { connectto } for path=00494E554445565F4C4F43414C5F534F434B45545F53455256455200 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=unix_stream_socket permissive=0

These lines are repeated constantly in logcat and there is nothing more.

I can see from this output that both the app and the service are considered as untrusted. I know that API 23 requests run time permissions, and both the service and the app request and get write, read, and internet runtime permissions.

My service manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mycompany.myservice"
      android:versionCode="1"
      android:versionName="2.03.0018.104"
    >

    <uses-feature android:name="android.hardware.usb.host" />
    <uses-sdk android:minSdkVersion="23" />

    <!-- Required for TCP IPC and for local socket --> 
    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- Copy data to SDcard + recording + temporary files -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application android:label="@string/app_name">

        <!-- Attacher hack -->
        <activity
            android:name="mynamespace.myservice$myserviceLauncher"
            android:theme="@android:style/Theme.NoDisplay"
            android:launchMode="singleInstance"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
            </intent-filter>
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" android:resource="@xml/device_filter" />
        </activity>

        <!-- Detacher hack -->
        <receiver android:name="mynamespace.myservice$Detacher">
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
            </intent-filter>
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" android:resource="@xml/device_filter" />
        </receiver>

        <service android:name="mynamespace.myservice">
        </service>

    </application>
</manifest> 

My app manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mycompany.myapp"
    android:versionCode="1"
    android:versionName="2.01.00.06"
>

<uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="23" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:hardwareAccelerated="true"
    android:allowBackup="true"
    android:largeHeap="true"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:logo="@drawable/icon"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="landscape" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

Is there a way to add both my service and my app to the trusted applications list?

Or how else can I make the local socket connection to work?


Solution

  • This is due to further tightening of the platform's SE policies in order to remove potential attack vectors. From the AOSP release info for Android 6.0:

    System Hardening. Hardening of the system via policies enforced by SELinux. This offers better isolation between users, IOCTL filtering, reduce threat of exposed services, further tightening of SELinux domains, and extremely limited /proc access.

    The SE policy file for untrusted apps (the default for 3rd party app installs) explicitly disables access to UNIX domain sockets:

    https://android.googlesource.com/platform/external/sepolicy/+/android-6.0.1_r81/untrusted_app.te#141

    The recommended practice for Android is not to use sockets for IPC, use binder for method like invocation.