Allow packages.list access with new GID.
The FUSE daemon is using packages.list to map from package name to
appId after it drops permissions, so create a new "package_info" GID
to grant read access.
Also switches FileUtils to use Libcore.os.
Change-Id: I9451ca4e90e8a985526805c6df0888a244a1db36
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 97ea99d..4d48fd4 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -17,10 +17,17 @@
package android.os;
import android.util.Log;
+import android.util.Slog;
+
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -58,9 +65,84 @@
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
- public static native int setPermissions(String file, int mode, int uid, int gid);
+ /**
+ * Set owner and mode of of given {@link File}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(File path, int mode, int uid, int gid) {
+ return setPermissions(path.getAbsolutePath(), mode, uid, gid);
+ }
- public static native int getUid(String file);
+ /**
+ * Set owner and mode of of given path.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(String path, int mode, int uid, int gid) {
+ try {
+ Libcore.os.chmod(path, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chmod(" + path + "): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.chown(path, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chown(" + path + "): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set owner and mode of of given {@link FileDescriptor}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
+ try {
+ Libcore.os.fchmod(fd, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchmod(): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.fchown(fd, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchown(): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return owning UID of given path, otherwise -1.
+ */
+ public static int getUid(String path) {
+ try {
+ return Libcore.os.stat(path).st_uid;
+ } catch (ErrnoException e) {
+ return -1;
+ }
+ }
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ab0543d..cf9ddb3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -100,12 +100,6 @@
public static final int DRM_UID = 1019;
/**
- * Defines the GID for the group that allows write access to the SD card.
- * @hide
- */
- public static final int SDCARD_RW_GID = 1015;
-
- /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
@@ -130,11 +124,18 @@
public static final int MEDIA_RW_GID = 1023;
/**
+ * Access to installed package details
+ * @hide
+ */
+ public static final int PACKAGE_INFO_GID = 1032;
+
+ /**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
* to applications.
*/
public static final int FIRST_APPLICATION_UID = 10000;
+
/**
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ccc0089..04351da 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,7 +499,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 0aaa2b1..d1245da 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -33,46 +33,6 @@
namespace android {
-jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
- jstring file, jint mode,
- jint uid, jint gid)
-{
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (uid >= 0 || gid >= 0) {
- int res = chown(file8.string(), uid, gid);
- if (res != 0) {
- return errno;
- }
- }
- return chmod(file8.string(), mode) == 0 ? 0 : errno;
-}
-
-jint android_os_FileUtils_getUid(JNIEnv* env, jobject clazz, jstring file)
-{
- struct stat stats;
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (stat(file8.string(), &stats) < 0) {
- return -1;
- }
- return stats.st_uid;
-}
-
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
if (path == NULL) {
@@ -95,8 +55,6 @@
}
static const JNINativeMethod methods[] = {
- {"setPermissions", "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
- {"getUid", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getUid},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
};
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 163536a..e78362b 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -22,6 +22,8 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.PACKAGE_INFO_GID;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -117,6 +119,7 @@
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+
final HashMap<String, PackageSetting> mPackages =
new HashMap<String, PackageSetting>();
// List of replaced system applications
@@ -201,6 +204,8 @@
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
+ FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
@@ -1369,13 +1374,15 @@
-1, -1);
// Write package list file now, use a JournaledFile.
- //
- File tempFile = new File(mPackageListFilename.toString() + ".tmp");
+ File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
- fstr = new FileOutputStream(journal.chooseForWrite());
+ final File writeTarget = journal.chooseForWrite();
+ fstr = new FileOutputStream(writeTarget);
str = new BufferedOutputStream(fstr);
try {
+ FileUtils.setPermissions(fstr.getFD(), 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
ApplicationInfo ai = pkg.pkg.applicationInfo;
@@ -1400,6 +1407,7 @@
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
+ // system/core/sdcard/sdcard.c
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -1421,11 +1429,6 @@
journal.rollback();
}
- FileUtils.setPermissions(mPackageListFilename.toString(),
- FileUtils.S_IRUSR|FileUtils.S_IWUSR
- |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
- -1, -1);
-
writeAllUsersPackageRestrictionsLPr();
return;