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

Commit 4efe9403 authored by Ben Gruver's avatar Ben Gruver
Browse files

Initial implementation of IntentFirewall functionality

This has the full filter functionality, but is currently only
able to block Activity intents. Logging intents, or blocking
service/broadcast intents is not yet implemented.

Change-Id: Ied3d8dedf982e17bcbdff3e328eeb87477954df7
parent cdee9727
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
            boolean printedHeader = false;
            F filter;
            for (int i=0; i<N && (filter=a[i]) != null; i++) {
                if (packageName != null && !packageName.equals(packageForFilter(filter))) {
                if (packageName != null && !isPackageForFilter(packageName, filter)) {
                    continue;
                }
                if (title != null) {
@@ -357,11 +357,11 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
    }

    /**
     * Return the package that owns this filter.  This must be implemented to
     * provide correct filtering of Intents that have specified a package name
     * they are to be delivered to.
     * Returns whether this filter is owned by this package. This must be
     * implemented to provide correct filtering of Intents that have
     * specified a package name they are to be delivered to.
     */
    protected abstract String packageForFilter(F filter);
    protected abstract boolean isPackageForFilter(String packageName, F filter);

    protected abstract F[] newArray(int size);

@@ -556,7 +556,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
            }

            // Is delivery being limited to filters owned by a particular package?
            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
            if (packageName != null && !isPackageForFilter(packageName, filter)) {
                if (debug) {
                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
                }
@@ -710,8 +710,8 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
    }

    private final IntentResolverOld<F, R> mOldResolver = new IntentResolverOld<F, R>() {
        @Override protected String packageForFilter(F filter) {
            return IntentResolver.this.packageForFilter(filter);
        @Override protected boolean isPackageForFilter(String packageName, F filter) {
            return IntentResolver.this.isPackageForFilter(packageName, filter);
        }
        @Override protected boolean allowFilterResult(F filter, List<R> dest) {
            return IntentResolver.this.allowFilterResult(filter, dest);
+6 −6
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ public abstract class IntentResolverOld<F extends IntentFilter, R extends Object
            boolean printedHeader = false;
            for (int i=0; i<N; i++) {
                F filter = a.get(i);
                if (packageName != null && !packageName.equals(packageForFilter(filter))) {
                if (packageName != null && !isPackageForFilter(packageName, filter)) {
                    continue;
                }
                if (title != null) {
@@ -336,11 +336,11 @@ public abstract class IntentResolverOld<F extends IntentFilter, R extends Object
    }

    /**
     * Return the package that owns this filter.  This must be implemented to
     * provide correct filtering of Intents that have specified a package name
     * they are to be delivered to.
     * Returns whether this filter is owned by this package. This must be
     * implemented to provide correct filtering of Intents that have
     * specified a package name they are to be delivered to.
     */
    protected abstract String packageForFilter(F filter);
    protected abstract boolean isPackageForFilter(String packageName, F filter);
    
    @SuppressWarnings("unchecked")
    protected R newResult(F filter, int match, int userId) {
@@ -529,7 +529,7 @@ public abstract class IntentResolverOld<F extends IntentFilter, R extends Object
            }

            // Is delivery being limited to filters owned by a particular package?
            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
            if (packageName != null && !isPackageForFilter(packageName, filter)) {
                if (debug) {
                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
                }
+15 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.server.ProcessMap;
import com.android.server.SystemServer;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.AppTransition;
import com.android.server.wm.WindowManagerService;
@@ -274,6 +275,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    public ActivityStack mMainStack;
    public IntentFirewall mIntentFirewall;
    private final boolean mHeadless;
    // Whether we should show our dialogs (ANR, crash, etc) or just perform their
@@ -570,8 +573,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        @Override
        protected String packageForFilter(BroadcastFilter filter) {
            return filter.packageName;
        protected boolean isPackageForFilter(String packageName, BroadcastFilter filter) {
            return packageName.equals(filter.packageName);
        }
    };
@@ -1467,6 +1470,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        m.mContext = context;
        m.mFactoryTest = factoryTest;
        m.mMainStack = new ActivityStack(m, context, true, thr.mLooper);
        m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());
        m.mBatteryStatsService.publish(context);
        m.mUsageStatsService.publish(context);
@@ -4943,6 +4947,14 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    class IntentFirewallInterface implements IntentFirewall.AMSInterface {
        public int checkComponentPermission(String permission, int pid, int uid,
                int owningUid, boolean exported) {
            return ActivityManagerService.this.checkComponentPermission(permission, pid, uid,
                    owningUid, exported);
        }
    }
    /**
     * This can be called with or without the global lock held.
     */
+19 −15
Original line number Diff line number Diff line
@@ -2489,6 +2489,7 @@ final class ActivityStack {
        int err = ActivityManager.START_SUCCESS;

        ProcessRecord callerApp = null;

        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
@@ -2592,18 +2593,23 @@ final class ActivityStack {
            throw new SecurityException(msg);
        }

        boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
                callerApp==null?null:callerApp.info, callingPackage, callingUid, callingPid,
                resolvedType, aInfo);

        if (mMainStack) {
            if (mService.mController != null) {
                boolean abort = false;
                try {
                    // The Intent we give to the watcher has the extra data
                    // stripped off, since it can contain private information.
                    Intent watchIntent = intent.cloneFilter();
                    abort = !mService.mController.activityStarting(watchIntent,
                    abort |= !mService.mController.activityStarting(watchIntent,
                            aInfo.applicationInfo.packageName);
                } catch (RemoteException e) {
                    mService.mController = null;
                }
            }
        }

        if (abort) {
            if (resultRecord != null) {
@@ -2617,8 +2623,6 @@ final class ActivityStack {
            ActivityOptions.abort(options);
            return ActivityManager.START_SUCCESS;
        }
            }
        }

        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration,
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.firewall;

import android.content.Intent;
import android.content.pm.ApplicationInfo;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

class AndFilter extends FilterList {
    @Override
    public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
            String callerPackage, int callerUid, int callerPid, String resolvedType,
            ApplicationInfo resolvedApp) {
        for (int i=0; i<children.size(); i++) {
            if (!children.get(i).matches(ifw, intent, callerApp, callerPackage, callerUid,
                    callerPid, resolvedType, resolvedApp)) {
                return false;
            }
        }
        return true;
    }

    public static final FilterFactory FACTORY = new FilterFactory("and") {
        @Override
        public Filter newFilter(XmlPullParser parser)
                throws IOException, XmlPullParserException {
            return new AndFilter().readFromXml(parser);
        }
    };
}
Loading