Validate package name passed to setApplicationRestrictions.

This adds validation that the package name passed to
setApplicationRestrictions is in the correct format. This will avoid
an issue where a path could be entered resulting in a file being
written to an unexpected place.

Bug: 239701237
Test: atest UserManagerServiceTest
Change-Id: I1ab2b7228470f10ec26fe3a608ae540cfc9e9a96
(cherry picked from commit 31a582490d)
Merged-In: I1ab2b7228470f10ec26fe3a608ae540cfc9e9a96
This commit is contained in:
Oli Lan
2022-08-19 17:08:13 +01:00
parent 7902b42dfe
commit 8c2c7b4164
2 changed files with 48 additions and 0 deletions

View File

@@ -88,6 +88,7 @@ import android.stats.devicepolicy.DevicePolicyEnums;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Slog;
@@ -4499,6 +4500,13 @@ public class UserManagerService extends IUserManager.Stub {
public void setApplicationRestrictions(String packageName, Bundle restrictions,
@UserIdInt int userId) {
checkSystemOrRoot("set application restrictions");
String validationResult = validateName(packageName);
if (validationResult != null) {
if (packageName.contains("../")) {
EventLog.writeEvent(0x534e4554, "239701237", -1, "");
}
throw new IllegalArgumentException("Invalid package name: " + validationResult);
}
if (restrictions != null) {
restrictions.setDefusable(true);
}
@@ -4525,6 +4533,39 @@ public class UserManagerService extends IUserManager.Stub {
mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
}
/**
* Check if the given name is valid.
*
* Note: the logic is taken from FrameworkParsingPackageUtils in master, edited to remove
* unnecessary parts. Copied here for a security fix.
*
* @param name The name to check.
* @return null if it's valid, error message if not
*/
@VisibleForTesting
static String validateName(String name) {
final int n = name.length();
boolean front = true;
for (int i = 0; i < n; i++) {
final char c = name.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
front = false;
continue;
}
if (!front) {
if ((c >= '0' && c <= '9') || c == '_') {
continue;
}
if (c == '.') {
front = true;
continue;
}
}
return "bad character '" + c + "'";
}
return null;
}
private int getUidForPackage(String packageName) {
final long ident = Binder.clearCallingIdentity();
try {

View File

@@ -86,6 +86,13 @@ public class UserManagerServiceTest extends AndroidTestCase {
}
}
public void testValidateName() {
assertNull(UserManagerService.validateName("android"));
assertNull(UserManagerService.validateName("com.company.myapp"));
assertNotNull(UserManagerService.validateName("/../../data"));
assertNotNull(UserManagerService.validateName("/dir"));
}
private Bundle createBundle() {
Bundle result = new Bundle();
// Tests for 6 allowed types: Integer, Boolean, String, String[], Bundle and Parcelable[]