Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c8dd55a authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix bug 1829561 ("am profile" with bad filename kills process).

The am command is now the one that takes care of opening the target file,
handling the opened file descriptor to the process that will be profiled.
This allows you to send profile data to anywhere the shell can access, and
avoids any problems coming up from the target process trying to open the
file.
parent 0bc7b849
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -26,10 +26,13 @@ import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.view.IWindowManager;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.Set;

@@ -446,6 +449,8 @@ public class Am {
            return;
        }
        
        ParcelFileDescriptor fd = null;
        
        String cmd = nextArg();
        if ("start".equals(cmd)) {
            start = true;
@@ -455,6 +460,16 @@ public class Am {
                showUsage();
                return;
            }
            try {
                fd = ParcelFileDescriptor.open(
                        new File(profileFile),
                        ParcelFileDescriptor.MODE_CREATE |
                        ParcelFileDescriptor.MODE_TRUNCATE |
                        ParcelFileDescriptor.MODE_READ_WRITE);
            } catch (FileNotFoundException e) {
                System.err.println("Error: Unable to open file: " + profileFile);
                return;
            }
        } else if (!"stop".equals(cmd)) {
            System.err.println("Error: Profile command " + cmd + " not valid");
            showUsage();
@@ -462,8 +477,8 @@ public class Am {
        }
        
        try {
            if (!mAm.profileControl(process, start, profileFile)) {
                System.out.println("PROFILE FAILED on process " + process);
            if (!mAm.profileControl(process, start, profileFile, fd)) {
                System.err.println("PROFILE FAILED on process " + process);
                return;
            }
        } catch (IllegalArgumentException e) {
+10 −2
Original line number Diff line number Diff line
@@ -986,7 +986,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            String process = data.readString();
            boolean start = data.readInt() != 0;
            String path = data.readString();
            boolean res = profileControl(process, start, path);
            ParcelFileDescriptor fd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            boolean res = profileControl(process, start, path, fd);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
@@ -2232,7 +2234,7 @@ class ActivityManagerProxy implements IActivityManager
    }
    
    public boolean profileControl(String process, boolean start,
            String path) throws RemoteException
            String path, ParcelFileDescriptor fd) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
@@ -2240,6 +2242,12 @@ class ActivityManagerProxy implements IActivityManager
        data.writeString(process);
        data.writeInt(start ? 1 : 0);
        data.writeString(path);
        if (fd != null) {
            data.writeInt(1);
            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0);
        reply.readException();
        boolean res = reply.readInt() != 0;
+23 −8
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -74,6 +75,7 @@ import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -1236,6 +1238,11 @@ public final class ActivityThread {
        String who;
    }

    private static final class ProfilerControlData {
        String path;
        ParcelFileDescriptor fd;
    }

    private final class ApplicationThread extends ApplicationThreadNative {
        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
        private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -1494,8 +1501,11 @@ public final class ActivityThread {
            }
        }
        
        public void profilerControl(boolean start, String path) {
            queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0);
        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
            ProfilerControlData pcd = new ProfilerControlData();
            pcd.path = path;
            pcd.fd = fd;
            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
        }

        public void setSchedulingGroup(int group) {
@@ -1838,7 +1848,7 @@ public final class ActivityThread {
                    handleActivityConfigurationChanged((IBinder)msg.obj);
                    break;
                case PROFILER_CONTROL:
                    handleProfilerControl(msg.arg1 != 0, (String)msg.obj);
                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
                    break;
                case CREATE_BACKUP_AGENT:
                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -3618,15 +3628,20 @@ public final class ActivityThread {
        performConfigurationChanged(r.activity, mConfiguration);
    }

    final void handleProfilerControl(boolean start, String path) {
    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
        if (start) {
            File file = new File(path);
            file.getParentFile().mkdirs();
            try {
                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
                        8 * 1024 * 1024, 0);
            } catch (RuntimeException e) {
                Log.w(TAG, "Profiling failed on path " + path
                Log.w(TAG, "Profiling failed on path " + pcd.path
                        + " -- can the process access this path?");
            } finally {
                try {
                    pcd.fd.close();
                } catch (IOException e) {
                    Log.w(TAG, "Failure closing profile fd", e);
                }
            }
        } else {
            Debug.stopMethodTracing();
+12 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Parcel;
@@ -331,7 +332,9 @@ public abstract class ApplicationThreadNative extends Binder
            data.enforceInterface(IApplicationThread.descriptor);
            boolean start = data.readInt() != 0;
            String path = data.readString();
            profilerControl(start, path);
            ParcelFileDescriptor fd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            profilerControl(start, path, fd);
            return true;
        }
        
@@ -711,11 +714,18 @@ class ApplicationThreadProxy implements IApplicationThread {
        data.recycle();
    }
    
    public void profilerControl(boolean start, String path) throws RemoteException {
    public void profilerControl(boolean start, String path,
            ParcelFileDescriptor fd) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeInt(start ? 1 : 0);
        data.writeString(path);
        if (fd != null) {
            data.writeInt(1);
            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(PROFILER_CONTROL_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
+1 −1
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ public interface IActivityManager extends IInterface {
    
    // Turn on/off profiling in a particular process.
    public boolean profileControl(String process, boolean start,
            String path) throws RemoteException;
            String path, ParcelFileDescriptor fd) throws RemoteException;
    
    public boolean shutdown(int timeout) throws RemoteException;
    
Loading