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