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

Commit 08511dab authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/26695417',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/26695417', 'googleplex-android-review.googlesource.com/26941037', 'googleplex-android-review.googlesource.com/26747994'] into security-aosp-udc-release.

Change-Id: I47fbedc0a2bd3c9b8299e35fc00410444db9e6d0
parents 7026bffa 7905ffaa
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -93,6 +93,9 @@ class ZygoteConnection {
            throw ex;
        }

        if (peer.getUid() != Process.SYSTEM_UID) {
            throw new ZygoteSecurityException("Only system UID is allowed to connect to Zygote.");
        }
        isEof = false;
    }

+53 −29
Original line number Diff line number Diff line
@@ -353,6 +353,18 @@ jstring com_android_internal_os_ZygoteCommandBuffer_nativeNextArg(JNIEnv* env, j
  return result;
}

static uid_t getSocketPeerUid(int socket, const std::function<void(const std::string&)>& fail_fn) {
  struct ucred credentials;
  socklen_t cred_size = sizeof credentials;
  if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
      || cred_size != sizeof credentials) {
    fail_fn(CREATE_ERROR("Failed to get socket credentials, %s",
                         strerror(errno)));
  }

  return credentials.uid;
}

// Read all lines from the current command into the buffer, and then reset the buffer, so
// we will start reading again at the beginning of the command, starting with the argument
// count. And we don't need access to the fd to do so.
@@ -412,19 +424,12 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
    fail_fn_z("Failed to retrieve session socket timeout");
  }

  struct ucred credentials;
  socklen_t cred_size = sizeof credentials;
  if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
      || cred_size != sizeof credentials) {
    fail_fn_1(CREATE_ERROR("ForkRepeatedly failed to get initial credentials, %s",
                           strerror(errno)));
  uid_t peerUid = getSocketPeerUid(session_socket, fail_fn_1);
  if (peerUid != static_cast<uid_t>(expected_uid)) {
    return JNI_FALSE;
  }

  bool first_time = true;
  do {
    if (credentials.uid != expected_uid) {
      return JNI_FALSE;
    }
    n_buffer->readAllLines(first_time ? fail_fn_1 : fail_fn_n);
    n_buffer->reset();
    int pid = zygote::forkApp(env, /* no pipe FDs */ -1, -1, session_socket_fds,
@@ -454,22 +459,48 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
    // Clear buffer and get count from next command.
    n_buffer->clear();
    for (;;) {
      bool valid_session_socket = true;
      // Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
      int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
      if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
        if (n_buffer->getCount(fail_fn_z) != 0) {
          break;
        }  // else disconnected;
        } else {
          // Session socket was disconnected
          valid_session_socket = false;
          close(session_socket);
        }
      } else if (poll_res == 0 || (fd_structs[ZYGOTE_IDX].revents & POLLIN) == 0) {
        fail_fn_z(
            CREATE_ERROR("Poll returned with no descriptors ready! Poll returned %d", poll_res));
      }
      int new_fd = -1;
      do {
        // We've now seen either a disconnect or connect request.
      close(session_socket);
      int new_fd = TEMP_FAILURE_RETRY(accept(zygote_socket_fd, nullptr, nullptr));
        new_fd = TEMP_FAILURE_RETRY(accept(zygote_socket_fd, nullptr, nullptr));
        if (new_fd == -1) {
          fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
        }
        uid_t newPeerUid = getSocketPeerUid(new_fd, fail_fn_1);
        if (newPeerUid != static_cast<uid_t>(expected_uid)) {
          ALOGW("Dropping new connection with a mismatched uid %d\n", newPeerUid);
          close(new_fd);
          new_fd = -1;
        } else {
          // If we still have a valid session socket, close it now
          if (valid_session_socket) {
              close(session_socket);
          }
          valid_session_socket = true;
        }
      } while (!valid_session_socket);

      // At this point we either have a valid new connection (new_fd > 0), or
      // an existing session socket we can poll on
      if (new_fd == -1) {
        // The new connection wasn't valid, and we still have an old one; retry polling
        continue;
      }
      if (new_fd != session_socket) {
        // Move new_fd back to the old value, so that we don't have to change Java-level data
        // structures to reflect a change. This implicitly closes the old one.
@@ -489,13 +520,6 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
        fail_fn_z(CREATE_ERROR("Failed to set send timeout for socket %d: %s",
                               session_socket, strerror(errno)));
      }
      if (getsockopt(session_socket, SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1) {
        fail_fn_z(CREATE_ERROR("ForkMany failed to get credentials: %s", strerror(errno)));
      }
      if (cred_size != sizeof credentials) {
        fail_fn_z(CREATE_ERROR("ForkMany credential size = %d, should be %d",
                               cred_size, static_cast<int>(sizeof credentials)));
      }
    }
    first_time = false;
  } while (n_buffer->isSimpleForkCommand(minUid, fail_fn_n));
+11 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ public class ParcelableListBinder<T extends Parcelable> extends Binder {
    private static final int END_OF_PARCEL = 0;
    private static final int ITEM_CONTINUED = 1;

    private final Class<T> mListElementsClass;
    private final Consumer<List<T>> mConsumer;

    private final Object mLock = new Object();
@@ -61,9 +62,11 @@ public class ParcelableListBinder<T extends Parcelable> extends Binder {
    /**
     * Creates an instance.
     *
     * @param listElementsClass the class of the list elements.
     * @param consumer a consumer that consumes the list received
     */
    public ParcelableListBinder(@NonNull Consumer<List<T>> consumer) {
    public ParcelableListBinder(Class<T> listElementsClass, @NonNull Consumer<List<T>> consumer) {
        mListElementsClass = listElementsClass;
        mConsumer = consumer;
    }

@@ -83,7 +86,13 @@ public class ParcelableListBinder<T extends Parcelable> extends Binder {
                mCount = data.readInt();
            }
            while (i < mCount && data.readInt() != END_OF_PARCEL) {
                mList.add(data.readParcelable(null));
                Object object = data.readParcelable(null);
                if (mListElementsClass.isAssignableFrom(object.getClass())) {
                    // Checking list items are of compaitible types to validate against malicious
                    // apps calling it directly via reflection with non compilable items.
                    // See b/317048338 for more details
                    mList.add((T) object);
                }
                i++;
            }
            if (i >= mCount) {
+8 −6
Original line number Diff line number Diff line
@@ -1197,7 +1197,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR

        @Override
        public IBinder getBinderForSetQueue() throws RemoteException {
            return new ParcelableListBinder<QueueItem>((list) -> {
            return new ParcelableListBinder<QueueItem>(
                    QueueItem.class,
                    (list) -> {
                        synchronized (mLock) {
                            mQueue = list;
                        }
+20 −3
Original line number Diff line number Diff line
@@ -6160,9 +6160,26 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                packageStateWrite.setMimeGroup(mimeGroup, mimeTypesSet);
            });
            if (mComponentResolver.updateMimeGroup(snapshotComputer(), packageName, mimeGroup)) {
                Binder.withCleanCallingIdentity(() ->
                Binder.withCleanCallingIdentity(() -> {
                    mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
                                UserHandle.USER_ALL));
                            UserHandle.USER_ALL);
                    // Send the ACTION_PACKAGE_CHANGED when the mimeGroup has changes
                    final Computer snapShot = snapshotComputer();
                    final ArrayList<String> components = new ArrayList<>(
                            Collections.singletonList(packageName));
                    final int appId = packageState.getAppId();
                    final int[] userIds = resolveUserIds(UserHandle.USER_ALL);
                    final String reason = "The mimeGroup is changed";
                    for (int i = 0; i < userIds.length; i++) {
                        final PackageUserStateInternal pkgUserState =
                                packageState.getUserStates().get(userIds[i]);
                        if (pkgUserState != null && pkgUserState.isInstalled()) {
                            final int packageUid = UserHandle.getUid(userIds[i], appId);
                            sendPackageChangedBroadcast(snapShot, packageName,
                                    true /* dontKillApp */, components, packageUid, reason);
                        }
                    }
                });
            }

            scheduleWriteSettings();