下面列出了android.os.Process#SHELL_UID 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType, String callingPackage) {
int callingUid = Binder.getCallingUid();
if (callingUid != Process.SHELL_UID && !checkAndroidPermissions(callingUid, callingPackage)) {
return false;
}
switch (profileType) {
case ArtManager.PROFILE_APPS :
return SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
case ArtManager.PROFILE_BOOT_IMAGE:
return (Build.IS_USERDEBUG || Build.IS_ENG) &&
SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false) &&
SystemProperties.getBoolean("dalvik.vm.profilebootimage", false);
default:
throw new IllegalArgumentException("Invalid profile type:" + profileType);
}
}
private static String resolvePackageName(int uid, String packageName) {
if (uid == Process.ROOT_UID) {
return "root";
} else if (uid == Process.SHELL_UID) {
return "com.android.shell";
} else if (uid == Process.MEDIA_UID) {
return "media";
} else if (uid == Process.AUDIOSERVER_UID) {
return "audioserver";
} else if (uid == Process.CAMERASERVER_UID) {
return "cameraserver";
} else if (uid == Process.SYSTEM_UID && packageName == null) {
return "android";
}
return packageName;
}
private static int resolveUid(String packageName) {
if (packageName == null) {
return -1;
}
switch (packageName) {
case "root":
return Process.ROOT_UID;
case "shell":
return Process.SHELL_UID;
case "media":
return Process.MEDIA_UID;
case "audioserver":
return Process.AUDIOSERVER_UID;
case "cameraserver":
return Process.CAMERASERVER_UID;
}
return -1;
}
private void validateExtras(int callingUid, Bundle extras) {
if (extras.containsKey(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG)) {
switch (callingUid) {
case Process.ROOT_UID:
case Process.SHELL_UID:
case Process.SYSTEM_UID:
break; // Okay
default:
final String msg = "Invalid extras specified.";
Log.w(TAG, msg + " requestsync -f/-F needs to run on 'adb shell'");
throw new SecurityException(msg);
}
}
}
private void validateExtras(int callingUid, Bundle extras) {
if (extras.containsKey(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG)) {
switch (callingUid) {
case Process.ROOT_UID:
case Process.SHELL_UID:
case Process.SYSTEM_UID:
break; // Okay
default:
final String msg = "Invalid extras specified.";
Log.w(TAG, msg + " requestsync -f/-F needs to run on 'adb shell'");
throw new SecurityException(msg);
}
}
}
private int adjustPermissionProtectionFlagsLocked(
int protectionLevel, String packageName, int uid) {
// Signature permission flags area always reported
final int protectionLevelMasked = protectionLevel
& (PermissionInfo.PROTECTION_NORMAL
| PermissionInfo.PROTECTION_DANGEROUS
| PermissionInfo.PROTECTION_SIGNATURE);
if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
return protectionLevel;
}
// System sees all flags.
final int appId = UserHandle.getAppId(uid);
if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
|| appId == Process.SHELL_UID) {
return protectionLevel;
}
// Normalize package name to handle renamed packages and static libs
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null) {
return protectionLevel;
}
if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
return protectionLevelMasked;
}
// Apps that target O see flags for all protection levels.
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return protectionLevel;
}
if (ps.getAppId() != appId) {
return protectionLevel;
}
return protectionLevel;
}
/**
* Checks if the calling user is the shell user and if it is, it checks if it can
* to take a profile snapshot of the give package:
* - on debuggable builds the shell user can take profile snapshots of any app.
* - on non-debuggable builds the shell user can only take snapshots of debuggable apps.
*
* Returns true iff the callingUid is the shell uid and the shell is allowed snapshot profiles.
*
* Note that the root users will go through the regular {@link #checkAndroidPermissions) checks.
*/
private boolean checkShellPermissions(@ProfileType int profileType, String packageName,
int callingUid) {
if (callingUid != Process.SHELL_UID) {
return false;
}
if (RoSystemProperties.DEBUGGABLE) {
return true;
}
if (profileType == ArtManager.PROFILE_BOOT_IMAGE) {
// The shell cannot profile the boot image on non-debuggable builds.
return false;
}
PackageInfo info = null;
try {
info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0);
} catch (RemoteException ignored) {
// Should not happen.
}
if (info == null) {
return false;
}
// On user builds the shell can only profile debuggable apps.
return (info.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE)
== ApplicationInfo.FLAG_DEBUGGABLE;
}
public static void enforceShellRestriction(String restriction, int callingUid, int userHandle) {
if (callingUid == Process.SHELL_UID) {
if (userHandle >= 0
&& PackageManagerService.sUserManager.hasUserRestriction(
restriction, userHandle)) {
throw new SecurityException("Shell does not have permission to access user "
+ userHandle);
} else if (userHandle < 0) {
Slog.e(PackageManagerService.TAG, "Unable to check shell permission for user "
+ userHandle + "\n\t" + Debug.getCallers(3));
}
}
}
public static String resolveCallingPackage() {
switch (Binder.getCallingUid()) {
case Process.ROOT_UID: {
return "root";
}
case Process.SHELL_UID: {
return "com.android.shell";
}
default: {
return null;
}
}
}
private void enforceShell(String method) {
final int callingUid = Binder.getCallingUid();
if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
throw new SecurityException("Non-shell user attempted to call " + method);
}
}
private void enforceStatusBarOrShell() {
if (Binder.getCallingUid() == Process.SHELL_UID) {
return;
}
enforceStatusBar();
}
private boolean isCallerShell() {
final int callingUid = Binder.getCallingUid();
return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
}
private int runGetPermissions(String authority) {
if (Binder.getCallingUid() != Process.SHELL_UID
&& Binder.getCallingUid() != Process.ROOT_UID) {
getOutPrintWriter().println("Only shell can get permissions");
return -1;
}
Context context = mService.getContext();
long ident = Binder.clearCallingIdentity();
try {
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(authority)
.build();
if (!SliceProvider.SLICE_TYPE.equals(context.getContentResolver().getType(uri))) {
getOutPrintWriter().println(authority + " is not a slice provider");
return -1;
}
Bundle b = context.getContentResolver().call(uri, SliceProvider.METHOD_GET_PERMISSIONS,
null, null);
if (b == null) {
getOutPrintWriter().println("An error occurred getting permissions");
return -1;
}
String[] permissions = b.getStringArray(SliceProvider.EXTRA_RESULT);
final PrintWriter pw = getOutPrintWriter();
Set<String> listedPackages = new ArraySet<>();
if (permissions != null && permissions.length != 0) {
List<PackageInfo> apps =
context.getPackageManager().getPackagesHoldingPermissions(permissions, 0);
for (PackageInfo app : apps) {
pw.println(app.packageName);
listedPackages.add(app.packageName);
}
}
for (String pkg : mService.getAllPackagesGranted(authority)) {
if (!listedPackages.contains(pkg)) {
pw.println(pkg);
listedPackages.add(pkg);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return 0;
}
private void enforceShell(String method) {
final int callingUid = Binder.getCallingUid();
if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
throw new SecurityException("Non-shell user attempted to call " + method);
}
}
@Override
public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,
IntentSender statusReceiver, int userId) throws RemoteException {
final int callingUid = Binder.getCallingUid();
mPermissionManager.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
mAppOps.checkPackage(callingUid, callerPackageName);
}
// Check whether the caller is device owner or affiliated profile owner, in which case we do
// it silently.
final int callingUserId = UserHandle.getUserId(callingUid);
DevicePolicyManagerInternal dpmi =
LocalServices.getService(DevicePolicyManagerInternal.class);
final boolean isDeviceOwnerOrAffiliatedProfileOwner =
dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
&& dpmi.isUserAffiliatedWithDevice(callingUserId);
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, versionedPackage.getPackageName(),
isDeviceOwnerOrAffiliatedProfileOwner, userId);
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
== PackageManager.PERMISSION_GRANTED) {
// Sweet, call straight through!
mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
} else if (isDeviceOwnerOrAffiliatedProfileOwner) {
// Allow the device owner and affiliated profile owner to silently delete packages
// Need to clear the calling identity to get DELETE_PACKAGES permission
long ident = Binder.clearCallingIdentity();
try {
mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
ApplicationInfo appInfo = mPm.getApplicationInfo(callerPackageName, 0, userId);
if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES,
null);
}
// Take a short detour to confirm with user
final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null));
intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder());
adapter.onUserActionRequired(intent);
}
}
private boolean isCallerShell() {
final int callingUid = injectBinderCallingUid();
return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
}
private boolean isCallerShell() {
final int callingUid = Binder.getCallingUid();
return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
}
int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
int allowMode, String name, String callerPackage) {
final int callingUserId = UserHandle.getUserId(callingUid);
if (callingUserId == userId) {
return userId;
}
// Note that we may be accessing mCurrentUserId outside of a lock...
// shouldn't be a big deal, if this is being called outside
// of a locked context there is intrinsically a race with
// the value the caller will receive and someone else changing it.
// We assume that USER_CURRENT_OR_SELF will use the current user; later
// we will switch to the calling user if access to the current user fails.
int targetUserId = unsafeConvertIncomingUser(userId);
if (callingUid != 0 && callingUid != SYSTEM_UID) {
final boolean allow;
if (mInjector.isCallerRecents(callingUid)
&& callingUserId == getCurrentUserId()
&& isSameProfileGroup(callingUserId, targetUserId)) {
// If the caller is Recents and it is running in the current user, we then allow it
// to access its profiles.
allow = true;
} else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
// If the caller has this permission, they always pass go. And collect $200.
allow = true;
} else if (allowMode == ALLOW_FULL_ONLY) {
// We require full access, sucks to be you.
allow = false;
} else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
// If the caller does not have either permission, they are always doomed.
allow = false;
} else if (allowMode == ALLOW_NON_FULL) {
// We are blanket allowing non-full access, you lucky caller!
allow = true;
} else if (allowMode == ALLOW_NON_FULL_IN_PROFILE) {
// We may or may not allow this depending on whether the two users are
// in the same profile.
allow = isSameProfileGroup(callingUserId, targetUserId);
} else {
throw new IllegalArgumentException("Unknown mode: " + allowMode);
}
if (!allow) {
if (userId == UserHandle.USER_CURRENT_OR_SELF) {
// In this case, they would like to just execute as their
// owner user instead of failing.
targetUserId = callingUserId;
} else {
StringBuilder builder = new StringBuilder(128);
builder.append("Permission Denial: ");
builder.append(name);
if (callerPackage != null) {
builder.append(" from ");
builder.append(callerPackage);
}
builder.append(" asks to run as user ");
builder.append(userId);
builder.append(" but is calling from user ");
builder.append(UserHandle.getUserId(callingUid));
builder.append("; this requires ");
builder.append(INTERACT_ACROSS_USERS_FULL);
if (allowMode != ALLOW_FULL_ONLY) {
builder.append(" or ");
builder.append(INTERACT_ACROSS_USERS);
}
String msg = builder.toString();
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
}
if (!allowAll) {
ensureNotSpecialUser(targetUserId);
}
// Check shell permission
if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
if (hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId)) {
throw new SecurityException("Shell does not have permission to access user "
+ targetUserId + "\n " + Debug.getCallers(3));
}
}
return targetUserId;
}