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

Commit 887be321 authored by Hyundo Moon's avatar Hyundo Moon
Browse files

Prevent the session count from being compromised

Some ways are found to reduce the session count multiple times by
destroying only one session:

1) Call MediaSession#release() multiple times.
2) Call MediaSession#release() and make the process crash

This CL fixes this problem by checking whether the session is already
destroyed in the MediaSessionService.

Also, another hole was found that calling MediaSession2#close()
decrements the session count, although the count does not increase
when creating the MediaSession2. This can be badly used for creating
MediaSession above limit. This CL also fixes this problem.

Bug: 143672815
Test: atest MediaSessionTest
Change-Id: I65225acc98d4bb0ce5cbb7e692675dd05ead635c
parent 2e000710
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ public class MediaSession2Record implements MediaSessionRecordImpl {
    private boolean mIsConnected;
    @GuardedBy("mLock")
    private int mPolicies;
    @GuardedBy("mLock")
    private boolean mIsClosed;

    public MediaSession2Record(Session2Token sessionToken, MediaSessionService service,
            Looper handlerLooper, int policies) {
@@ -119,12 +121,20 @@ public class MediaSession2Record implements MediaSessionRecordImpl {
    @Override
    public void close() {
        synchronized (mLock) {
            mIsClosed = true;
            // Call close regardless of the mIsAvailable. This may be called when it's not yet
            // connected.
            mController.close();
        }
    }

    @Override
    public boolean isClosed() {
        synchronized (mLock) {
            return mIsClosed;
        }
    }

    @Override
    public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
            KeyEvent ke, int sequenceId, ResultReceiver cb) {
+7 −0
Original line number Diff line number Diff line
@@ -420,6 +420,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
        }
    }

    @Override
    public boolean isClosed() {
        synchronized (mLock) {
            return mDestroyed;
        }
    }

    /**
     * Sends media button.
     *
+5 −0
Original line number Diff line number Diff line
@@ -154,4 +154,9 @@ public interface MediaSessionRecordImpl extends AutoCloseable {
     */
    @Override
    void close();

    /**
     * Returns whether {@link #close()} is called before.
     */
    boolean isClosed();
}
+13 −7
Original line number Diff line number Diff line
@@ -434,9 +434,14 @@ public class MediaSessionService extends SystemService implements Monitor {
        if (DEBUG) {
            Log.d(TAG, "Destroying " + session);
        }
        if (session.isClosed()) {
            Log.w(TAG, "Destroying already destroyed session. Ignoring.");
            return;
        }

        FullUserRecord user = getFullUserRecordLocked(session.getUserId());

        if (user != null) {
        if (user != null && session instanceof MediaSessionRecord) {
            final int uid = session.getUid();
            final int sessionCount = user.mUidToSessionCount.get(uid, 0);
            if (sessionCount <= 0) {
@@ -570,6 +575,13 @@ public class MediaSessionService extends SystemService implements Monitor {
                throw new RuntimeException("Session request from invalid user.");
            }

            final int sessionCount = user.mUidToSessionCount.get(callerUid, 0);
            if (sessionCount >= SESSION_CREATION_LIMIT_PER_UID
                    && !hasMediaControlPermission(callerPid, callerUid)) {
                throw new RuntimeException("Created too many sessions. count="
                        + sessionCount + ")");
            }

            final MediaSessionRecord session;
            try {
                session = new MediaSessionRecord(callerPid, callerUid, userId,
@@ -579,12 +591,6 @@ public class MediaSessionService extends SystemService implements Monitor {
                throw new RuntimeException("Media Session owner died prematurely.", e);
            }

            final int sessionCount = user.mUidToSessionCount.get(callerUid, 0);
            if (sessionCount >= SESSION_CREATION_LIMIT_PER_UID
                    && !hasMediaControlPermission(callerPid, callerUid)) {
                throw new RuntimeException("Created too many sessions. count="
                        + sessionCount + ")");
            }
            user.mUidToSessionCount.put(callerUid, sessionCount + 1);

            user.mPriorityStack.addSession(session);