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;