• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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