Home | History | Annotate | Download | only in audioflinger
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <binder/AppOpsManager.h>
     18 #include <binder/IPCThreadState.h>
     19 #include <binder/IServiceManager.h>
     20 #include <binder/PermissionCache.h>
     21 #include <private/android_filesystem_config.h>
     22 #include "ServiceUtilities.h"
     23 
     24 /* When performing permission checks we do not use permission cache for
     25  * runtime permissions (protection level dangerous) as they may change at
     26  * runtime. All other permissions (protection level normal and dangerous)
     27  * can be cached as they never change. Of course all permission checked
     28  * here are platform defined.
     29  */
     30 
     31 namespace android {
     32 
     33 static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_AUDIO");
     34 
     35 // Not valid until initialized by AudioFlinger constructor.  It would have to be
     36 // re-initialized if the process containing AudioFlinger service forks (which it doesn't).
     37 // This is often used to validate binder interface calls within audioserver
     38 // (e.g. AudioPolicyManager to AudioFlinger).
     39 pid_t getpid_cached;
     40 
     41 // A trusted calling UID may specify the client UID as part of a binder interface call.
     42 // otherwise the calling UID must be equal to the client UID.
     43 bool isTrustedCallingUid(uid_t uid) {
     44     switch (uid) {
     45     case AID_MEDIA:
     46     case AID_AUDIOSERVER:
     47         return true;
     48     default:
     49         return false;
     50     }
     51 }
     52 
     53 static String16 resolveCallingPackage(PermissionController& permissionController,
     54         const String16& opPackageName, uid_t uid) {
     55     if (opPackageName.size() > 0) {
     56         return opPackageName;
     57     }
     58     // In some cases the calling code has no access to the package it runs under.
     59     // For example, code using the wilhelm framework's OpenSL-ES APIs. In this
     60     // case we will get the packages for the calling UID and pick the first one
     61     // for attributing the app op. This will work correctly for runtime permissions
     62     // as for legacy apps we will toggle the app op for all packages in the UID.
     63     // The caveat is that the operation may be attributed to the wrong package and
     64     // stats based on app ops may be slightly off.
     65     Vector<String16> packages;
     66     permissionController.getPackagesForUid(uid, packages);
     67     if (packages.isEmpty()) {
     68         ALOGE("No packages for uid %d", uid);
     69         return opPackageName; // empty string
     70     }
     71     return packages[0];
     72 }
     73 
     74 static inline bool isAudioServerOrRoot(uid_t uid) {
     75     // AID_ROOT is OK for command-line tests.  Native unforked audioserver always OK.
     76     return uid == AID_ROOT || uid == AID_AUDIOSERVER ;
     77 }
     78 
     79 static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
     80         uid_t uid, bool start) {
     81     // Okay to not track in app ops as audio server is us and if
     82     // device is rooted security model is considered compromised.
     83     if (isAudioServerOrRoot(uid)) return true;
     84 
     85     // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
     86     // may open a record track on behalf of a client.  Note that pid may be a tid.
     87     // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
     88     PermissionController permissionController;
     89     const bool ok = permissionController.checkPermission(sAndroidPermissionRecordAudio, pid, uid);
     90     if (!ok) {
     91         ALOGE("Request requires %s", String8(sAndroidPermissionRecordAudio).c_str());
     92         return false;
     93     }
     94 
     95     String16 resolvedOpPackageName = resolveCallingPackage(
     96             permissionController, opPackageName, uid);
     97     if (resolvedOpPackageName.size() == 0) {
     98         return false;
     99     }
    100 
    101     AppOpsManager appOps;
    102     const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
    103     if (start) {
    104         if (appOps.startOpNoThrow(op, uid, resolvedOpPackageName, /*startIfModeDefault*/ false)
    105                 != AppOpsManager::MODE_ALLOWED) {
    106             ALOGE("Request denied by app op: %d", op);
    107             return false;
    108         }
    109     } else {
    110         if (appOps.noteOp(op, uid, resolvedOpPackageName) != AppOpsManager::MODE_ALLOWED) {
    111             ALOGE("Request denied by app op: %d", op);
    112             return false;
    113         }
    114     }
    115 
    116     return true;
    117 }
    118 
    119 bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
    120     return checkRecordingInternal(opPackageName, pid, uid, /*start*/ false);
    121 }
    122 
    123 bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
    124      return checkRecordingInternal(opPackageName, pid, uid, /*start*/ true);
    125 }
    126 
    127 void finishRecording(const String16& opPackageName, uid_t uid) {
    128     // Okay to not track in app ops as audio server is us and if
    129     // device is rooted security model is considered compromised.
    130     if (isAudioServerOrRoot(uid)) return;
    131 
    132     PermissionController permissionController;
    133     String16 resolvedOpPackageName = resolveCallingPackage(
    134             permissionController, opPackageName, uid);
    135     if (resolvedOpPackageName.size() == 0) {
    136         return;
    137     }
    138 
    139     AppOpsManager appOps;
    140     const int32_t op = appOps.permissionToOpCode(sAndroidPermissionRecordAudio);
    141     appOps.finishOp(op, uid, resolvedOpPackageName);
    142 }
    143 
    144 bool captureAudioOutputAllowed(pid_t pid, uid_t uid) {
    145     if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
    146     static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
    147     bool ok = PermissionCache::checkPermission(sCaptureAudioOutput, pid, uid);
    148     if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
    149     return ok;
    150 }
    151 
    152 bool captureHotwordAllowed(pid_t pid, uid_t uid) {
    153     // CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
    154     bool ok = recordingAllowed(String16(""), pid, uid);
    155 
    156     if (ok) {
    157         static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
    158         // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    159         ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed);
    160     }
    161     if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
    162     return ok;
    163 }
    164 
    165 bool settingsAllowed() {
    166     if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
    167     static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
    168     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    169     bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
    170     if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
    171     return ok;
    172 }
    173 
    174 bool modifyAudioRoutingAllowed() {
    175     static const String16 sModifyAudioRoutingAllowed("android.permission.MODIFY_AUDIO_ROUTING");
    176     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    177     bool ok = PermissionCache::checkCallingPermission(sModifyAudioRoutingAllowed);
    178     if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING");
    179     return ok;
    180 }
    181 
    182 bool dumpAllowed() {
    183     // don't optimize for same pid, since mediaserver never dumps itself
    184     static const String16 sDump("android.permission.DUMP");
    185     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    186     bool ok = PermissionCache::checkCallingPermission(sDump);
    187     // convention is for caller to dump an error message to fd instead of logging here
    188     //if (!ok) ALOGE("Request requires android.permission.DUMP");
    189     return ok;
    190 }
    191 
    192 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid) {
    193     static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
    194     bool ok = PermissionCache::checkPermission(sModifyPhoneState, pid, uid);
    195     if (!ok) ALOGE("Request requires android.permission.MODIFY_PHONE_STATE");
    196     return ok;
    197 }
    198 
    199 } // namespace android
    200