1 /* 2 * Copyright (C) 2015 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 package com.android.packageinstaller.permission.utils; 18 19 import android.Manifest; 20 import android.content.pm.PackageInfo; 21 import android.content.pm.PackageManager; 22 import android.content.pm.PermissionInfo; 23 import android.text.TextUtils; 24 import android.util.ArrayMap; 25 import android.util.ArraySet; 26 import android.util.EventLog; 27 import android.util.Log; 28 29 import com.android.packageinstaller.permission.model.AppPermissionGroup; 30 import com.android.packageinstaller.permission.model.Permission; 31 32 import java.util.ArrayList; 33 import java.util.List; 34 35 public final class SafetyNetLogger { 36 37 // The log tag used by SafetyNet to pick entries from the event log. 38 private static final int SNET_NET_EVENT_LOG_TAG = 0x534e4554; 39 40 // Log tag for the result of permissions request. 41 private static final String PERMISSIONS_REQUESTED = "individual_permissions_requested"; 42 43 // Log tag for the result of permissions toggling. 44 private static final String PERMISSIONS_TOGGLED = "individual_permissions_toggled"; 45 public static final String LOG_TAG = SafetyNetLogger.class.getSimpleName(); 46 SafetyNetLogger()47 private SafetyNetLogger() { 48 /* do nothing */ 49 } 50 logPermissionsRequested(PackageInfo packageInfo, List<AppPermissionGroup> groups)51 public static void logPermissionsRequested(PackageInfo packageInfo, 52 List<AppPermissionGroup> groups) { 53 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_REQUESTED, 54 packageInfo.applicationInfo.uid, buildChangedPermissionForPackageMessage( 55 packageInfo.packageName, groups)); 56 } 57 58 /** 59 * Log that permission groups have been toggled for the purpose of safety net. 60 * 61 * <p>The groups might refer to different permission groups and different apps. 62 * 63 * @param groups The groups toggled 64 */ logPermissionsToggled(ArraySet<AppPermissionGroup> groups)65 public static void logPermissionsToggled(ArraySet<AppPermissionGroup> groups) { 66 ArrayMap<String, ArrayList<AppPermissionGroup>> groupsByPackage = new ArrayMap<>(); 67 68 int numGroups = groups.size(); 69 for (int i = 0; i < numGroups; i++) { 70 AppPermissionGroup group = groups.valueAt(i); 71 72 ArrayList<AppPermissionGroup> groupsForThisPackage = groupsByPackage.get( 73 group.getApp().packageName); 74 if (groupsForThisPackage == null) { 75 groupsForThisPackage = new ArrayList<>(); 76 groupsByPackage.put(group.getApp().packageName, groupsForThisPackage); 77 } 78 79 groupsForThisPackage.add(group); 80 if (group.getBackgroundPermissions() != null) { 81 groupsForThisPackage.add(group.getBackgroundPermissions()); 82 } 83 } 84 85 int numPackages = groupsByPackage.size(); 86 for (int i = 0; i < numPackages; i++) { 87 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_TOGGLED, 88 android.os.Process.myUid(), buildChangedPermissionForPackageMessage( 89 groupsByPackage.keyAt(i), groupsByPackage.valueAt(i))); 90 } 91 } 92 93 /** 94 * Log that a permission group has been toggled for the purpose of safety net. 95 * 96 * @param group The group toggled. 97 */ logPermissionToggled(AppPermissionGroup group)98 public static void logPermissionToggled(AppPermissionGroup group) { 99 ArraySet groups = new ArraySet<AppPermissionGroup>(1); 100 groups.add(group); 101 logPermissionsToggled(groups); 102 } 103 buildChangedPermissionForGroup(AppPermissionGroup group, StringBuilder builder)104 private static void buildChangedPermissionForGroup(AppPermissionGroup group, 105 StringBuilder builder) { 106 int permissionCount = group.getPermissions().size(); 107 for (int permissionNum = 0; permissionNum < permissionCount; permissionNum++) { 108 Permission permission = group.getPermissions().get(permissionNum); 109 110 if (builder.length() > 0) { 111 builder.append(';'); 112 } 113 114 builder.append(permission.getName()).append('|'); 115 builder.append(permission.isGrantedIncludingAppOp()).append('|'); 116 builder.append(permission.getFlags()); 117 } 118 } 119 buildChangedPermissionForPackageMessage(String packageName, List<AppPermissionGroup> groups)120 private static String buildChangedPermissionForPackageMessage(String packageName, 121 List<AppPermissionGroup> groups) { 122 StringBuilder builder = new StringBuilder(); 123 124 builder.append(packageName).append(':'); 125 126 int groupCount = groups.size(); 127 for (int groupNum = 0; groupNum < groupCount; groupNum++) { 128 AppPermissionGroup group = groups.get(groupNum); 129 130 buildChangedPermissionForGroup(group, builder); 131 if (group.getBackgroundPermissions() != null) { 132 buildChangedPermissionForGroup(group.getBackgroundPermissions(), builder); 133 } 134 } 135 136 return builder.toString(); 137 } 138 139 /** 140 * Log if the given package has defined a permission in the undefined group. 141 * 142 * @param pm A PackageManager to look up the package. 143 * @param packageName The name of the package to check. 144 */ logIfHasUndefinedPermissionGroup(PackageManager pm, String packageName)145 public static void logIfHasUndefinedPermissionGroup(PackageManager pm, String packageName) { 146 try { //Avoid crashing for any reason 147 PermissionInfo[] permissions = 148 pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS).permissions; 149 if (permissions == null) { 150 return; 151 } 152 for (PermissionInfo permission : permissions) { 153 if (TextUtils.equals(permission.group, Manifest.permission_group.UNDEFINED)) { 154 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, "153879813"); 155 } 156 } 157 } catch (Throwable e) { 158 Log.e(LOG_TAG, "Unable to log undefined permission event for " + packageName + ".", e); 159 } 160 } 161 } 162