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

Commit 0acd9c8f authored by Al Sutton's avatar Al Sutton Committed by Android (Google) Code Review
Browse files

Merge "Add protection against an access-after-free issue if cancel() is called...

Merge "Add protection against an access-after-free issue if cancel() is called after a device connection has been closed."
parents e940f70d ca53d07a
Loading
Loading
Loading
Loading
+36 −7
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ public class UsbDeviceConnection {

    private final CloseGuard mCloseGuard = CloseGuard.get();

    private final Object mLock = new Object();

    /**
     * UsbDevice should only be instantiated by UsbService implementation
     * @hide
@@ -62,6 +64,8 @@ public class UsbDeviceConnection {

    /* package */ boolean open(String name, ParcelFileDescriptor pfd, @NonNull Context context) {
        mContext = context.getApplicationContext();

        synchronized (mLock) {
            boolean wasOpened = native_open(name, pfd.getFileDescriptor());

            if (wasOpened) {
@@ -70,6 +74,14 @@ public class UsbDeviceConnection {

            return wasOpened;
        }
    }

    /***
     * @return If this connection is currently open and usable.
     */
    boolean isOpen() {
        return mNativeContext != 0;
    }

    /**
     * @return The application context the connection was created for.
@@ -80,6 +92,21 @@ public class UsbDeviceConnection {
        return mContext;
    }

    /**
     * Cancel a request which relates to this connection.
     *
     * @return true if the request was successfully cancelled.
     */
    /* package */ boolean cancelRequest(UsbRequest request) {
        synchronized (mLock) {
            if (!isOpen()) {
                return false;
            }

            return request.cancelIfOpen();
        }
    }

    /**
     * Releases all system resources related to the device.
     * Once the object is closed it cannot be used again.
@@ -87,11 +114,13 @@ public class UsbDeviceConnection {
     * to retrieve a new instance to reestablish communication with the device.
     */
    public void close() {
        if (mNativeContext != 0) {
        synchronized (mLock) {
            if (isOpen()) {
                native_close();
                mCloseGuard.close();
            }
        }
    }

    /**
     * Returns the native file descriptor for the device, or
+24 −0
Original line number Diff line number Diff line
@@ -362,6 +362,30 @@ public class UsbRequest {
     * @return true if cancelling succeeded
     */
    public boolean cancel() {
        if (mConnection == null) {
            return false;
        }

        return mConnection.cancelRequest(this);
    }

    /**
     * Cancels a pending queue operation (for use when the UsbDeviceConnection associated
     * with this request is synchronized). This ensures we don't have a race where the
     * device is closed and then the request is canceled which would lead to a
     * use-after-free because the cancel operation uses the device connection
     * information freed in the when UsbDeviceConnection is closed.<br/>
     *
     * This method assumes the connected is not closed while this method is executed.
     *
     * @return true if cancelling succeeded.
     */
    /* package */ boolean cancelIfOpen() {
        if (mNativeContext == 0 || (mConnection != null && !mConnection.isOpen())) {
            Log.w(TAG,
                    "Detected attempt to cancel a request on a connection which isn't open");
            return false;
        }
        return native_cancel();
    }