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

Commit 41cba494 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add UID check when starting MediaProjection sessions" into main

parents ca941d48 facac371
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -64,3 +64,13 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "media_projection"
    name: "start_uid_check"
    description: "Improves permission model when starting MediaProjection session"
    bug: "419269649"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+33 −0
Original line number Diff line number Diff line
@@ -734,6 +734,35 @@ public final class MediaProjectionManagerService extends SystemService
        }
    }

    /**
     * Verifies whether the calling package name matches the calling app uid.
     *
     * @param context the context
     * @param callingPackage the calling application package name
     * @return {@code true} if the package name matches {@link Binder#getCallingUid()}, or
     *   {@code false} otherwise
     */
    private static boolean validateCallingPackageName(Context context, String callingPackage) {
        final int callingUid = Binder.getCallingUid();
        final long token = Binder.clearCallingIdentity();
        try {
            int packageUid = context.getPackageManager()
                    .getPackageUidAsUser(callingPackage, UserHandle.getUserId(callingUid));
            if (packageUid != callingUid) {
                Slog.e(TAG, "validatePackageName: App with package name " + callingPackage
                        + " is UID " + packageUid + " but caller is " + callingUid);
                return false;
            }
        } catch (PackageManager.NameNotFoundException e) {
            Slog.e(TAG, "validatePackageName: App with package name " + callingPackage
                    + " does not exist");
            return false;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return true;
    }

    private void dump(final PrintWriter pw) {
        pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)");
        synchronized (mLock) {
@@ -1189,6 +1218,10 @@ public final class MediaProjectionManagerService extends SystemService
                    mCountStarts++;
                    return;
                }
                if (Flags.startUidCheck() && validateCallingPackageName(mContext, packageName)) {
                    throw new SecurityException(
                            "This MediaProjection session was not granted to this application.");
                }

                if (REQUIRE_FG_SERVICE_FOR_PROJECTION
                        && requiresForegroundService() && !hasFGS) {
+23 −1
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import android.media.projection.StopReason;
import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.test.TestLooper;
@@ -123,7 +124,7 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@SuppressLint({"UseCheckPermission", "VisibleForTests", "MissingPermission"})
public class MediaProjectionManagerServiceTest {
    private static final int UID = 10;
    private static final int UID = Process.myUid();
    private static final String PACKAGE_NAME = "test.package";
    private final ApplicationInfo mAppInfo = new ApplicationInfo();
    private final PackageInfo mPackageInfo = new PackageInfo();
@@ -1347,6 +1348,27 @@ public class MediaProjectionManagerServiceTest {
                eq(projection.uid), anyInt());
    }

    @Test
    @EnableFlags(Flags.FLAG_START_UID_CHECK)
    public void createProjection_cannotBeStartedFromDifferentUid() throws Exception {
        doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(),
                any(ApplicationInfoFlags.class), any(UserHandle.class));
        doReturn(mPackageInfo).when(mPackageManager).getPackageInfoAsUser(anyString(), anyInt(),
                anyInt());
        int uid = 10;
        MediaProjectionManagerService.MediaProjection projection =
                mService.createProjectionInternal(
                        uid,
                        PACKAGE_NAME,
                        TYPE_SCREEN_CAPTURE,
                        /* isPermanentGrant= */ false,
                        UserHandle.CURRENT,
                        DEFAULT_DISPLAY);

        // Start MediaProjection from a different UID
        assertThrows(SecurityException.class, () -> projection.start(mIMediaProjectionCallback));
    }

    private void verifySetSessionWithContent(@RecordContent int content) {
        verify(mWindowManagerInternal, atLeastOnce()).setContentRecordingSession(
                mSessionCaptor.capture());