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 // Not valid until initialized by AudioFlinger constructor. It would have to be 34 // re-initialized if the process containing AudioFlinger service forks (which it doesn't). 35 pid_t getpid_cached; 36 recordingAllowed(const String16 & opPackageName)37bool recordingAllowed(const String16& opPackageName) { 38 // Note: We are getting the UID from the calling IPC thread state because all 39 // clients that perform recording create AudioRecord in their own processes 40 // and the system does not create AudioRecord objects on behalf of apps. This 41 // differs from playback where in some situations the system recreates AudioTrack 42 // instances associated with a client's MediaPlayer on behalf of this client. 43 // In the latter case we have to store the client UID and pass in along for 44 // security checks. 45 46 if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; 47 static const String16 sRecordAudio("android.permission.RECORD_AUDIO"); 48 49 // IMPORTANT: Don't use PermissionCache - a runtime permission and may change. 50 const bool ok = checkCallingPermission(sRecordAudio); 51 if (!ok) { 52 ALOGE("Request requires android.permission.RECORD_AUDIO"); 53 return false; 54 } 55 56 const uid_t uid = IPCThreadState::self()->getCallingUid(); 57 58 // To permit command-line native tests 59 if (uid == AID_ROOT) return true; 60 61 String16 checkedOpPackageName = opPackageName; 62 63 // In some cases the calling code has no access to the package it runs under. 64 // For example, code using the wilhelm framework's OpenSL-ES APIs. In this 65 // case we will get the packages for the calling UID and pick the first one 66 // for attributing the app op. This will work correctly for runtime permissions 67 // as for legacy apps we will toggle the app op for all packages in the UID. 68 // The caveat is that the operation may be attributed to the wrong package and 69 // stats based on app ops may be slightly off. 70 if (checkedOpPackageName.size() <= 0) { 71 sp<IServiceManager> sm = defaultServiceManager(); 72 sp<IBinder> binder = sm->getService(String16("permission")); 73 if (binder == 0) { 74 ALOGE("Cannot get permission service"); 75 return false; 76 } 77 78 sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder); 79 Vector<String16> packages; 80 81 permCtrl->getPackagesForUid(uid, packages); 82 83 if (packages.isEmpty()) { 84 ALOGE("No packages for calling UID"); 85 return false; 86 } 87 checkedOpPackageName = packages[0]; 88 } 89 90 AppOpsManager appOps; 91 if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, checkedOpPackageName) 92 != AppOpsManager::MODE_ALLOWED) { 93 ALOGE("Request denied by app op OP_RECORD_AUDIO"); 94 return false; 95 } 96 97 return true; 98 } 99 captureAudioOutputAllowed()100bool captureAudioOutputAllowed() { 101 if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; 102 static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT"); 103 // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. 104 bool ok = PermissionCache::checkCallingPermission(sCaptureAudioOutput); 105 if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT"); 106 return ok; 107 } 108 captureHotwordAllowed()109bool captureHotwordAllowed() { 110 static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD"); 111 // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. 112 bool ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed); 113 if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD"); 114 return ok; 115 } 116 settingsAllowed()117bool settingsAllowed() { 118 if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; 119 static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS"); 120 // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. 121 bool ok = PermissionCache::checkCallingPermission(sAudioSettings); 122 if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS"); 123 return ok; 124 } 125 modifyAudioRoutingAllowed()126bool modifyAudioRoutingAllowed() { 127 static const String16 sModifyAudioRoutingAllowed("android.permission.MODIFY_AUDIO_ROUTING"); 128 // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. 129 bool ok = PermissionCache::checkCallingPermission(sModifyAudioRoutingAllowed); 130 if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING"); 131 return ok; 132 } 133 dumpAllowed()134bool dumpAllowed() { 135 // don't optimize for same pid, since mediaserver never dumps itself 136 static const String16 sDump("android.permission.DUMP"); 137 // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. 138 bool ok = PermissionCache::checkCallingPermission(sDump); 139 // convention is for caller to dump an error message to fd instead of logging here 140 //if (!ok) ALOGE("Request requires android.permission.DUMP"); 141 return ok; 142 } 143 144 } // namespace android 145