mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2025-02-02 18:34:46 -05:00
Reconcile picks
Signed-off-by: Tavi <tavi@divested.dev>
This commit is contained in:
parent
7182e4d63a
commit
30b658da98
@ -132,7 +132,7 @@ index ed9b539c05df..83cc7a251ebf 100644
|
||||
|| newPkg.isForceQueryable()
|
||||
|| ArrayUtils.contains(mForceQueryableByDevicePackageNames,
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
index e637dcf531f0..80eaaba933d2 100644
|
||||
index 251d5a04f8ee..e0cd8fbbe31a 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
@@ -552,6 +552,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
@ -1,13 +0,0 @@
|
||||
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
|
||||
index bb8fa9e..6b836ad 100644
|
||||
--- a/core/java/android/companion/AssociationRequest.java
|
||||
+++ b/core/java/android/companion/AssociationRequest.java
|
||||
@@ -148,7 +148,7 @@
|
||||
|
||||
/** @hide */
|
||||
public void setSkipPrompt(boolean value) {
|
||||
- mSkipPrompt = true;
|
||||
+ mSkipPrompt = value;
|
||||
}
|
||||
|
||||
/** @hide */
|
@ -1,82 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bishoy Gendy <bishoygendy@google.com>
|
||||
Date: Thu, 11 Apr 2024 16:37:10 +0000
|
||||
Subject: [PATCH] Fix security vulnerability allowing apps to start from
|
||||
background
|
||||
|
||||
Bug: 317048338
|
||||
Test: Using the steps in b/317048338#comment12
|
||||
(cherry picked from commit c5fc8ea92c0aabbb2fdccc23b743c18a8bf62e64)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df3584bb93ab89d7e174f7d39e42d4b22cb92fe0)
|
||||
Merged-In: Ia91199fdb23beed27bde687fdca8fe5d3a5a4759
|
||||
Change-Id: Ia91199fdb23beed27bde687fdca8fe5d3a5a4759
|
||||
---
|
||||
.../media/session/ParcelableListBinder.java | 13 +++++++++++--
|
||||
.../android/server/media/MediaSessionRecord.java | 14 ++++++++------
|
||||
2 files changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/media/java/android/media/session/ParcelableListBinder.java b/media/java/android/media/session/ParcelableListBinder.java
|
||||
index bbf1e0889b68..d78828462b1e 100644
|
||||
--- a/media/java/android/media/session/ParcelableListBinder.java
|
||||
+++ b/media/java/android/media/session/ParcelableListBinder.java
|
||||
@@ -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) {
|
||||
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
index 66adbad5372e..a0679d7457a0 100644
|
||||
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
@@ -1095,12 +1095,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
|
||||
|
||||
@Override
|
||||
public IBinder getBinderForSetQueue() throws RemoteException {
|
||||
- return new ParcelableListBinder<QueueItem>((list) -> {
|
||||
- synchronized (mLock) {
|
||||
- mQueue = list;
|
||||
- }
|
||||
- mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
|
||||
- });
|
||||
+ return new ParcelableListBinder<QueueItem>(
|
||||
+ QueueItem.class,
|
||||
+ (list) -> {
|
||||
+ synchronized (mLock) {
|
||||
+ mQueue = list;
|
||||
+ }
|
||||
+ mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
|
||||
+ });
|
||||
}
|
||||
|
||||
@Override
|
@ -1,37 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yi-an Chen <theianchen@google.com>
|
||||
Date: Tue, 23 Apr 2024 21:17:44 +0000
|
||||
Subject: [PATCH] Fix security vulnerability of non-dynamic permission removal
|
||||
|
||||
The original removePermission() code in PermissionManagerServiceImpl
|
||||
missed a logical negation operator when handling non-dynamic
|
||||
permissions, causing both
|
||||
testPermissionPermission_nonDynamicPermission_permissionUnchanged and
|
||||
testRemovePermission_dynamicPermission_permissionRemoved tests in
|
||||
DynamicPermissionsTest to fail.
|
||||
|
||||
The corresponding test DynamicPermissionsTest is also updated in the
|
||||
other CL: ag/27073864
|
||||
|
||||
Bug: 321711213
|
||||
Test: DynamicPermissionsTest on sc-dev and tm-dev locally
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0ead58f69f5de82b00406316b333366d556239f1)
|
||||
Merged-In: Ia146d4098643d9c473f8c83d33a8a125a53101fc
|
||||
Change-Id: Ia146d4098643d9c473f8c83d33a8a125a53101fc
|
||||
---
|
||||
.../android/server/pm/permission/PermissionManagerService.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
|
||||
index 31babe0418b8..93f9e1c2295c 100644
|
||||
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
|
||||
@@ -687,7 +687,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
if (bp == null) {
|
||||
return;
|
||||
}
|
||||
- if (bp.isDynamic()) {
|
||||
+ if (!bp.isDynamic()) {
|
||||
// TODO: switch this back to SecurityException
|
||||
Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
|
||||
+ permName);
|
@ -1,175 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Coenen <maco@google.com>
|
||||
Date: Thu, 29 Feb 2024 12:03:05 +0000
|
||||
Subject: [PATCH] Verify UID of incoming Zygote connections.
|
||||
|
||||
Only the system UID should be allowed to connect to the Zygote. While
|
||||
for generic Zygotes this is also covered by SELinux policy, this is not
|
||||
true for App Zygotes: the preload code running in an app zygote could
|
||||
connect to another app zygote socket, if it had access to its (random)
|
||||
socket address.
|
||||
|
||||
On the Java layer, simply check the UID when the connection is made. In
|
||||
the native layer, this check was already present, but it actually didn't
|
||||
work in the case where we receive a new incoming connection on the
|
||||
socket, and receive a 'non-fork' command: in that case, we will simply
|
||||
exit the native loop, and let the Java layer handle the command, without
|
||||
any further UID checking.
|
||||
|
||||
Modified the native logic to drop new connections with a mismatching
|
||||
UID, and to keep serving the existing connection (if it was still
|
||||
there).
|
||||
|
||||
Bug: 319081336
|
||||
Test: manual
|
||||
(cherry picked from commit 2ffc7cb220e4220b7e108c4043a3f0f2a85b6508)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f1d4b34ad51b6ccb84ab042486923da8b2451e0f)
|
||||
Merged-In: I3f85a17107849e2cd3e82d6ef15c90b9e2f26532
|
||||
Change-Id: I3f85a17107849e2cd3e82d6ef15c90b9e2f26532
|
||||
---
|
||||
.../android/internal/os/ZygoteConnection.java | 3 +
|
||||
...ndroid_internal_os_ZygoteCommandBuffer.cpp | 81 ++++++++++++-------
|
||||
2 files changed, 56 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
index 993e4e7b4b3d..765901a043a0 100644
|
||||
--- a/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
index 248db76da71d..1ad64d58b7c9 100644
|
||||
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
@@ -341,6 +341,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.
|
||||
@@ -398,18 +410,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("ForkMany 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,
|
||||
@@ -439,30 +445,56 @@ 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));
|
||||
}
|
||||
- // 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));
|
||||
+ int new_fd = -1;
|
||||
+ do {
|
||||
+ // We've now seen either a disconnect or connect request.
|
||||
+ 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) {
|
||||
- fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
|
||||
+ // 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.
|
||||
- if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
|
||||
- fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
|
||||
- new_fd, session_socket, strerror(errno)));
|
||||
- }
|
||||
- close(new_fd); // On Linux, fd is closed even if EINTR is returned.
|
||||
+ // 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.
|
||||
+ if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
|
||||
+ fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
|
||||
+ new_fd, session_socket, strerror(errno)));
|
||||
+ }
|
||||
+ close(new_fd); // On Linux, fd is closed even if EINTR is returned.
|
||||
}
|
||||
// If we ever return, we effectively reuse the old Java ZygoteConnection.
|
||||
// None of its state needs to change.
|
||||
@@ -474,13 +506,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));
|
@ -1,291 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Su <wengsu@google.com>
|
||||
Date: Wed, 3 Apr 2024 10:45:43 +0800
|
||||
Subject: [PATCH] Restrict WifiDppConfiguratorActivity
|
||||
|
||||
- Don't show WifiDppConfiguratorActivity if user has DISALLOW_ADD_WIFI_CONFIG
|
||||
|
||||
- Don't show AddNetworkFragment if user has DISALLOW_ADD_WIFI_CONFIG
|
||||
|
||||
Fix: 299931076
|
||||
Flag: None
|
||||
Test: manual test with TestDPC
|
||||
atest -c SettingsUnitTests:AddNetworkFragmentTest \
|
||||
SettingsUnitTests:WifiDppConfiguratorActivityTest
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:254ba087c29503e8bcf01cc10082c3f393e7701f)
|
||||
Merged-In: I34afe0f698e2dc43eba59b25f5f3f4f61e70166a
|
||||
Change-Id: I34afe0f698e2dc43eba59b25f5f3f4f61e70166a
|
||||
---
|
||||
.../settings/wifi/AddNetworkFragment.java | 20 +++++
|
||||
.../wifi/dpp/WifiDppConfiguratorActivity.java | 20 +++++
|
||||
.../settings/wifi/AddNetworkFragmentTest.java | 74 +++++++++++++++++++
|
||||
.../dpp/WifiDppConfiguratorActivityTest.java | 74 +++++++++++++++++++
|
||||
4 files changed, 188 insertions(+)
|
||||
create mode 100644 tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
create mode 100644 tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
|
||||
diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
index 01d5ef1ca4..c50ab9ae24 100644
|
||||
--- a/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
+++ b/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
+import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.os.Bundle;
|
||||
+import android.os.UserManager;
|
||||
+import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -40,6 +45,7 @@ import com.android.settings.wifi.dpp.WifiDppUtils;
|
||||
*/
|
||||
public class AddNetworkFragment extends InstrumentedFragment implements WifiConfigUiBase2,
|
||||
View.OnClickListener {
|
||||
+ private static final String TAG = "AddNetworkFragment";
|
||||
|
||||
public static final String WIFI_CONFIG_KEY = "wifi_config_key";
|
||||
@VisibleForTesting
|
||||
@@ -57,6 +63,10 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
+ if (!isAddWifiConfigAllowed(getContext())) {
|
||||
+ getActivity().finish();
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,4 +214,14 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
|
||||
activity.setResult(Activity.RESULT_CANCELED);
|
||||
activity.finish();
|
||||
}
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ static boolean isAddWifiConfigAllowed(Context context) {
|
||||
+ UserManager userManager = context.getSystemService(UserManager.class);
|
||||
+ if (userManager != null && userManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)) {
|
||||
+ Log.e(TAG, "The user is not allowed to add Wi-Fi configuration.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
index ecaf9ee8fc..a658c16a8c 100644
|
||||
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.wifi.dpp;
|
||||
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@@ -96,6 +98,10 @@ public class WifiDppConfiguratorActivity extends WifiDppBaseActivity implements
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
+ if (!isAddWifiConfigAllowed(getApplicationContext())) {
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
String qrCode = savedInstanceState.getString(KEY_QR_CODE);
|
||||
@@ -116,6 +122,10 @@ public class WifiDppConfiguratorActivity extends WifiDppBaseActivity implements
|
||||
|
||||
@Override
|
||||
protected void handleIntent(Intent intent) {
|
||||
+ if (!isAddWifiConfigAllowed(getApplicationContext())) {
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
String action = intent != null ? intent.getAction() : null;
|
||||
if (action == null) {
|
||||
finish();
|
||||
@@ -384,4 +394,14 @@ public class WifiDppConfiguratorActivity extends WifiDppBaseActivity implements
|
||||
|
||||
return null;
|
||||
}
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ static boolean isAddWifiConfigAllowed(Context context) {
|
||||
+ UserManager userManager = context.getSystemService(UserManager.class);
|
||||
+ if (userManager != null && userManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)) {
|
||||
+ Log.e(TAG, "The user is not allowed to add Wi-Fi configuration.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java b/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
new file mode 100644
|
||||
index 0000000000..22d43c9bb4
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 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.settings.wifi;
|
||||
+
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+
|
||||
+import androidx.test.annotation.UiThreadTest;
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+@UiThreadTest
|
||||
+public class AddNetworkFragmentTest {
|
||||
+
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ private AddNetworkFragment mFragment;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+
|
||||
+ mFragment = new AddNetworkFragment();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasNoUserRestriction_returnTrue() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
|
||||
+
|
||||
+ assertThat(mFragment.isAddWifiConfigAllowed(mContext)).isTrue();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasUserRestriction_returnFalse() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
|
||||
+
|
||||
+ assertThat(mFragment.isAddWifiConfigAllowed(mContext)).isFalse();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
new file mode 100644
|
||||
index 0000000000..4d723dc184
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 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.settings.wifi.dpp;
|
||||
+
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+
|
||||
+import androidx.test.annotation.UiThreadTest;
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+@UiThreadTest
|
||||
+public class WifiDppConfiguratorActivityTest {
|
||||
+
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ private WifiDppConfiguratorActivity mActivity;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+
|
||||
+ mActivity = new WifiDppConfiguratorActivity();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasNoUserRestriction_returnTrue() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
|
||||
+
|
||||
+ assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isTrue();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasUserRestriction_returnFalse() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
|
||||
+
|
||||
+ assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isFalse();
|
||||
+ }
|
||||
+}
|
@ -1,260 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vova Sharaienko <sharaienko@google.com>
|
||||
Date: Thu, 20 Jul 2023 23:25:31 +0000
|
||||
Subject: [PATCH] Make executor thread a class member of MultiConditionTrigger
|
||||
|
||||
executorThread references class members after detaching. Making
|
||||
executorThread as class member and joining in MultiConditionTrigger
|
||||
destructor.
|
||||
|
||||
Ignore-AOSP-First: Security bugs merged into internal branch first
|
||||
Test: atest statsd_test
|
||||
Bug: 292160348
|
||||
Flag: NONE mainline module bug fix
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:262e2c8a5293483c98be498e60e1e5d15c6a0145)
|
||||
Merged-In: I7036eb3d506e8ca88e4a5faa6275dc4cba8020ee
|
||||
Change-Id: I7036eb3d506e8ca88e4a5faa6275dc4cba8020ee
|
||||
---
|
||||
statsd/src/utils/MultiConditionTrigger.cpp | 21 ++-
|
||||
statsd/src/utils/MultiConditionTrigger.h | 10 +-
|
||||
.../utils/MultiConditionTrigger_test.cpp | 121 ++++++++++++++++++
|
||||
3 files changed, 144 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/statsd/src/utils/MultiConditionTrigger.cpp b/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
index 43a69337..3088453e 100644
|
||||
--- a/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
+++ b/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
@@ -14,11 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define DEBUG false // STOPSHIP if true
|
||||
+#include "Log.h"
|
||||
|
||||
#include "MultiConditionTrigger.h"
|
||||
|
||||
-#include <thread>
|
||||
-
|
||||
using namespace std;
|
||||
|
||||
namespace android {
|
||||
@@ -31,8 +30,7 @@ MultiConditionTrigger::MultiConditionTrigger(const set<string>& conditionNames,
|
||||
mTrigger(trigger),
|
||||
mCompleted(mRemainingConditionNames.empty()) {
|
||||
if (mCompleted) {
|
||||
- thread executorThread([this] { mTrigger(); });
|
||||
- executorThread.detach();
|
||||
+ startExecutorThread();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +46,21 @@ void MultiConditionTrigger::markComplete(const string& conditionName) {
|
||||
doTrigger = mCompleted;
|
||||
}
|
||||
if (doTrigger) {
|
||||
- std::thread executorThread([this] { mTrigger(); });
|
||||
- executorThread.detach();
|
||||
+ startExecutorThread();
|
||||
}
|
||||
}
|
||||
+
|
||||
+void MultiConditionTrigger::startExecutorThread() {
|
||||
+ mExecutorThread = make_unique<thread>([this] { mTrigger(); });
|
||||
+}
|
||||
+
|
||||
+MultiConditionTrigger::~MultiConditionTrigger() {
|
||||
+ if (mExecutorThread != nullptr && mExecutorThread->joinable()) {
|
||||
+ VLOG("MultiConditionTrigger waiting on execution thread termination");
|
||||
+ mExecutorThread->join();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
diff --git a/statsd/src/utils/MultiConditionTrigger.h b/statsd/src/utils/MultiConditionTrigger.h
|
||||
index 51f60299..dee00713 100644
|
||||
--- a/statsd/src/utils/MultiConditionTrigger.h
|
||||
+++ b/statsd/src/utils/MultiConditionTrigger.h
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
+#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
@@ -27,8 +28,8 @@ namespace statsd {
|
||||
/**
|
||||
* This class provides a utility to wait for a set of named conditions to occur.
|
||||
*
|
||||
- * It will execute the trigger runnable in a detached thread once all conditions have been marked
|
||||
- * true.
|
||||
+ * It will execute the trigger runnable in a separate thread (which will be joined at instance
|
||||
+ * destructor time) once all conditions have been marked true.
|
||||
*/
|
||||
class MultiConditionTrigger {
|
||||
public:
|
||||
@@ -37,19 +38,24 @@ public:
|
||||
|
||||
MultiConditionTrigger(const MultiConditionTrigger&) = delete;
|
||||
MultiConditionTrigger& operator=(const MultiConditionTrigger&) = delete;
|
||||
+ ~MultiConditionTrigger();
|
||||
|
||||
// Mark a specific condition as true. If this condition has called markComplete already or if
|
||||
// the event was not specified in the constructor, the function is a no-op.
|
||||
void markComplete(const std::string& eventName);
|
||||
|
||||
private:
|
||||
+ void startExecutorThread();
|
||||
+
|
||||
mutable std::mutex mMutex;
|
||||
std::set<std::string> mRemainingConditionNames;
|
||||
std::function<void()> mTrigger;
|
||||
bool mCompleted;
|
||||
+ std::unique_ptr<std::thread> mExecutorThread;
|
||||
|
||||
FRIEND_TEST(MultiConditionTriggerTest, TestCountDownCalledBySameEventName);
|
||||
};
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
diff --git a/statsd/tests/utils/MultiConditionTrigger_test.cpp b/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
index 32cecd3b..b525f75e 100644
|
||||
--- a/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
+++ b/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
+#include "tests/statsd_test_util.h"
|
||||
+
|
||||
#ifdef __ANDROID__
|
||||
|
||||
using namespace std;
|
||||
@@ -166,6 +168,125 @@ TEST(MultiConditionTrigger, TestTriggerOnlyCalledOnce) {
|
||||
}
|
||||
}
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+class TriggerDependency {
|
||||
+public:
|
||||
+ TriggerDependency(mutex& lock, condition_variable& cv, bool& triggerCalled, int& triggerCount)
|
||||
+ : mLock(lock), mCv(cv), mTriggerCalled(triggerCalled), mTriggerCount(triggerCount) {
|
||||
+ }
|
||||
+
|
||||
+ void someMethod() {
|
||||
+ lock_guard lg(mLock);
|
||||
+ mTriggerCount++;
|
||||
+ mTriggerCalled = true;
|
||||
+ mCv.notify_all();
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ mutex& mLock;
|
||||
+ condition_variable& mCv;
|
||||
+ bool& mTriggerCalled;
|
||||
+ int& mTriggerCount;
|
||||
+};
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+TEST(MultiConditionTrigger, TestTriggerHasSleep) {
|
||||
+ const string t1 = "t1";
|
||||
+ set<string> conditionNames = {t1};
|
||||
+
|
||||
+ mutex lock;
|
||||
+ condition_variable cv;
|
||||
+ bool triggerCalled = false;
|
||||
+ int triggerCount = 0;
|
||||
+
|
||||
+ {
|
||||
+ TriggerDependency dependency(lock, cv, triggerCalled, triggerCount);
|
||||
+ MultiConditionTrigger trigger(conditionNames, [&dependency] {
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
+ dependency.someMethod();
|
||||
+ });
|
||||
+ trigger.markComplete(t1);
|
||||
+
|
||||
+ // Here dependency instance will go out of scope and the thread within MultiConditionTrigger
|
||||
+ // after delay will try to call method of already destroyed class instance
|
||||
+ // with leading crash if trigger execution thread is detached in MultiConditionTrigger
|
||||
+ // Instead since the MultiConditionTrigger destructor happens before TriggerDependency
|
||||
+ // destructor, MultiConditionTrigger destructor is waiting on execution thread termination
|
||||
+ // with thread::join
|
||||
+ }
|
||||
+ // At this moment the executor thread guaranteed terminated by MultiConditionTrigger destructor
|
||||
+
|
||||
+ // Ensure that the trigger fired.
|
||||
+ {
|
||||
+ unique_lock<mutex> unique_lk(lock);
|
||||
+ cv.wait(unique_lk, [&triggerCalled] { return triggerCalled; });
|
||||
+ EXPECT_TRUE(triggerCalled);
|
||||
+ EXPECT_EQ(triggerCount, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+TEST(MultiConditionTrigger, TestTriggerHasSleepEarlyTermination) {
|
||||
+ const string t1 = "t1";
|
||||
+ set<string> conditionNames = {t1};
|
||||
+
|
||||
+ mutex lock;
|
||||
+ condition_variable cv;
|
||||
+ bool triggerCalled = false;
|
||||
+ int triggerCount = 0;
|
||||
+
|
||||
+ std::condition_variable triggerTerminationFlag;
|
||||
+ std::mutex triggerTerminationFlagMutex;
|
||||
+ bool terminationRequested = false;
|
||||
+
|
||||
+ // used for error threshold tolerance due to wait_for() is involved
|
||||
+ const int64_t errorThresholdMs = 25;
|
||||
+ const int64_t triggerEarlyTerminationDelayMs = 100;
|
||||
+ const int64_t triggerStartNs = getElapsedRealtimeNs();
|
||||
+ {
|
||||
+ TriggerDependency dependency(lock, cv, triggerCalled, triggerCount);
|
||||
+ MultiConditionTrigger trigger(
|
||||
+ conditionNames, [&dependency, &triggerTerminationFlag, &triggerTerminationFlagMutex,
|
||||
+ &lock, &triggerCalled, &cv, &terminationRequested] {
|
||||
+ std::unique_lock<std::mutex> lk(triggerTerminationFlagMutex);
|
||||
+ if (triggerTerminationFlag.wait_for(
|
||||
+ lk, std::chrono::seconds(1),
|
||||
+ [&terminationRequested] { return terminationRequested; })) {
|
||||
+ // triggerTerminationFlag was notified - early termination is requested
|
||||
+ lock_guard lg(lock);
|
||||
+ triggerCalled = true;
|
||||
+ cv.notify_all();
|
||||
+ return;
|
||||
+ }
|
||||
+ dependency.someMethod();
|
||||
+ });
|
||||
+ trigger.markComplete(t1);
|
||||
+
|
||||
+ // notify to terminate trigger executor thread after triggerEarlyTerminationDelayMs
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(triggerEarlyTerminationDelayMs));
|
||||
+ {
|
||||
+ std::unique_lock<std::mutex> lk(triggerTerminationFlagMutex);
|
||||
+ terminationRequested = true;
|
||||
+ }
|
||||
+ triggerTerminationFlag.notify_all();
|
||||
+ }
|
||||
+ // At this moment the executor thread guaranteed terminated by MultiConditionTrigger destructor
|
||||
+
|
||||
+ // check that test duration is closer to 100ms rather to 1s
|
||||
+ const int64_t triggerEndNs = getElapsedRealtimeNs();
|
||||
+ EXPECT_LE(NanoToMillis(triggerEndNs - triggerStartNs),
|
||||
+ triggerEarlyTerminationDelayMs + errorThresholdMs);
|
||||
+
|
||||
+ // Ensure that the trigger fired but not the dependency.someMethod().
|
||||
+ {
|
||||
+ unique_lock<mutex> unique_lk(lock);
|
||||
+ cv.wait(unique_lk, [&triggerCalled] { return triggerCalled; });
|
||||
+ EXPECT_TRUE(triggerCalled);
|
||||
+ EXPECT_EQ(triggerCount, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
@ -1,51 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Omar Eissa <oeissa@google.com>
|
||||
Date: Mon, 15 Apr 2024 12:04:56 +0000
|
||||
Subject: [PATCH] Prevent insertion in other users storage volumes
|
||||
|
||||
Don't allow file insertion in other users storage volumes.
|
||||
This was already handled if DATA was explicitly set in content values,
|
||||
but was allowed if DATA was generated based on other values like RELATIVE_PATH and DISPLAY_NAME.
|
||||
|
||||
Insertion of files in other users storage volumes can be used by malicious apps
|
||||
to get access to other users files, since the same file would exist in both users MP databases
|
||||
which would lead to MP falsely assuming that the user has access to this file.
|
||||
|
||||
Bug: 294406604
|
||||
Test: atest MediaProviderTests
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df39f8486b25473d0bdbeed896ad917e3c793bf9)
|
||||
Merged-In: Ie219bbdbe28819421040e4c083b65ab47d8ebde6
|
||||
Change-Id: Ie219bbdbe28819421040e4c083b65ab47d8ebde6
|
||||
---
|
||||
src/com/android/providers/media/MediaProvider.java | 1 +
|
||||
tests/src/com/android/providers/media/MediaProviderTest.java | 5 ++---
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
|
||||
index 0d220aa5..71b652f1 100644
|
||||
--- a/src/com/android/providers/media/MediaProvider.java
|
||||
+++ b/src/com/android/providers/media/MediaProvider.java
|
||||
@@ -3275,6 +3275,7 @@ public class MediaProvider extends ContentProvider {
|
||||
|
||||
FileUtils.sanitizeValues(values, /*rewriteHiddenFileName*/ !isFuseThread());
|
||||
FileUtils.computeDataFromValues(values, volumePath, isFuseThread());
|
||||
+ assertFileColumnsConsistent(match, uri, values);
|
||||
|
||||
// Create result file
|
||||
File res = new File(values.getAsString(MediaColumns.DATA));
|
||||
diff --git a/tests/src/com/android/providers/media/MediaProviderTest.java b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
index 11fc327b..28463477 100644
|
||||
--- a/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
+++ b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
@@ -377,9 +377,8 @@ public class MediaProviderTest {
|
||||
@Test
|
||||
public void testInsertionWithInvalidFilePath_throwsIllegalArgumentException() {
|
||||
final ContentValues values = new ContentValues();
|
||||
- values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Android/media/com.example");
|
||||
- values.put(MediaStore.Images.Media.DISPLAY_NAME,
|
||||
- "./../../../../../../../../../../../data/media/test.txt");
|
||||
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Android/media/com.example/");
|
||||
+ values.put(MediaStore.Images.Media.DISPLAY_NAME, "data/media/test.txt");
|
||||
|
||||
IllegalArgumentException illegalArgumentException = Assert.assertThrows(
|
||||
IllegalArgumentException.class, () -> sIsolatedResolver.insert(
|
@ -1,63 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Delwiche <delwiche@google.com>
|
||||
Date: Mon, 22 Apr 2024 21:10:09 +0000
|
||||
Subject: [PATCH] Fix an authentication bypass bug in SMP
|
||||
|
||||
When pairing with BLE legacy pairing initiated
|
||||
from remote, authentication can be bypassed.
|
||||
This change fixes it.
|
||||
|
||||
Bug: 251514170
|
||||
Test: m com.android.btservices
|
||||
Test: manual run against PoC
|
||||
Ignore-AOSP-First: security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:25a3fcd487c799d5d9029b8646159a0b10143d97)
|
||||
Merged-In: I369a8fdd675eca731a7a488ed6a2be645058b795
|
||||
Change-Id: I369a8fdd675eca731a7a488ed6a2be645058b795
|
||||
---
|
||||
stack/smp/smp_act.cc | 12 ++++++++++++
|
||||
stack/smp/smp_int.h | 1 +
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc
|
||||
index 1863fdf51..47be844aa 100644
|
||||
--- a/stack/smp/smp_act.cc
|
||||
+++ b/stack/smp/smp_act.cc
|
||||
@@ -294,6 +294,7 @@ void smp_send_pair_rsp(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
void smp_send_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
SMP_TRACE_DEBUG("%s", __func__);
|
||||
smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
|
||||
+ p_cb->flags |= SMP_PAIR_FLAGS_CMD_CONFIRM_SENT;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -655,6 +656,17 @@ void smp_proc_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (!((p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) &&
|
||||
+ (p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT)) &&
|
||||
+ !(p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM_SENT)) {
|
||||
+ // in legacy pairing, the peer should send its rand after
|
||||
+ // we send our confirm
|
||||
+ tSMP_INT_DATA smp_int_data{};
|
||||
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
|
||||
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* save the SRand for comparison */
|
||||
STREAM_TO_ARRAY(p_cb->rrand.data(), p, OCTET16_LEN);
|
||||
}
|
||||
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
|
||||
index c13120182..b8c1a5b95 100644
|
||||
--- a/stack/smp/smp_int.h
|
||||
+++ b/stack/smp/smp_int.h
|
||||
@@ -211,6 +211,7 @@ typedef union {
|
||||
(1 << 7) /* used to resolve race condition */
|
||||
#define SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY \
|
||||
(1 << 8) /* used on peripheral to resolve race condition */
|
||||
+#define SMP_PAIR_FLAGS_CMD_CONFIRM_SENT (1 << 9)
|
||||
|
||||
/* check if authentication requirement need MITM protection */
|
||||
#define SMP_NO_MITM_REQUIRED(x) (((x)&SMP_AUTH_YN_BIT) == 0)
|
@ -1,63 +0,0 @@
|
||||
From d39bbaa57ea3e636aa581478ae27ef9829b75718 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Delwiche <delwiche@google.com>
|
||||
Date: Mon, 22 Apr 2024 21:10:09 +0000
|
||||
Subject: [PATCH] Fix an authentication bypass bug in SMP
|
||||
|
||||
When pairing with BLE legacy pairing initiated
|
||||
from remote, authentication can be bypassed.
|
||||
This change fixes it.
|
||||
|
||||
Bug: 251514170
|
||||
Test: m com.android.btservices
|
||||
Test: manual run against PoC
|
||||
Ignore-AOSP-First: security
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:25a3fcd487c799d5d9029b8646159a0b10143d97)
|
||||
Merged-In: I369a8fdd675eca731a7a488ed6a2be645058b795
|
||||
Change-Id: I369a8fdd675eca731a7a488ed6a2be645058b795
|
||||
---
|
||||
system/stack/smp/smp_act.cc | 12 ++++++++++++
|
||||
system/stack/smp/smp_int.h | 1 +
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc
|
||||
index 868c7b53118..d6021bbecd2 100644
|
||||
--- a/system/stack/smp/smp_act.cc
|
||||
+++ b/system/stack/smp/smp_act.cc
|
||||
@@ -291,6 +291,7 @@ void smp_send_pair_rsp(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
void smp_send_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
SMP_TRACE_DEBUG("%s", __func__);
|
||||
smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
|
||||
+ p_cb->flags |= SMP_PAIR_FLAGS_CMD_CONFIRM_SENT;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -665,6 +666,17 @@ void smp_proc_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (!((p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) &&
|
||||
+ (p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT)) &&
|
||||
+ !(p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM_SENT)) {
|
||||
+ // in legacy pairing, the peer should send its rand after
|
||||
+ // we send our confirm
|
||||
+ tSMP_INT_DATA smp_int_data{};
|
||||
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
|
||||
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* save the SRand for comparison */
|
||||
STREAM_TO_ARRAY(p_cb->rrand.data(), p, OCTET16_LEN);
|
||||
}
|
||||
diff --git a/system/stack/smp/smp_int.h b/system/stack/smp/smp_int.h
|
||||
index 5e731806de7..b2ab4776421 100644
|
||||
--- a/system/stack/smp/smp_int.h
|
||||
+++ b/system/stack/smp/smp_int.h
|
||||
@@ -222,6 +222,7 @@ typedef union {
|
||||
(1 << 7) /* used to resolve race condition */
|
||||
#define SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY \
|
||||
(1 << 8) /* used on peripheral to resolve race condition */
|
||||
+#define SMP_PAIR_FLAGS_CMD_CONFIRM_SENT (1 << 9)
|
||||
|
||||
/* check if authentication requirement need MITM protection */
|
||||
#define SMP_NO_MITM_REQUIRED(x) (((x)&SMP_AUTH_YN_BIT) == 0)
|
@ -1,51 +0,0 @@
|
||||
From a0afe17e817eb39f3de3251f7b040a5f6eebc577 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Chiang <chiangi@google.com>
|
||||
Date: Mon, 18 Mar 2024 02:46:56 +0000
|
||||
Subject: [PATCH] [PM] Send ACTION_PACKAGE_CHANGED when mimeGroups are changed
|
||||
|
||||
Test: atest CtsPackageManagerTestCases:PackageManagerShellCommandMultiUserTest
|
||||
Test: atest CtsPackageManagerTestCases:PackageManagerTest
|
||||
Bug: 297517712
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:81eb9f8294645684ce1fad39d5d4a00ef11736e4)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c160424ef22bffd25a9cc9bc7b901ae1b9721a72)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6d9520bb9be2e31fd43bb08f0017838bbd389883)
|
||||
Merged-In: I271a3526ea4555249e3a2797605269257330e0e9
|
||||
Change-Id: I271a3526ea4555249e3a2797605269257330e0e9
|
||||
---
|
||||
.../server/pm/PackageManagerService.java | 23 ++++++++++++++++---
|
||||
1 file changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
index f41b9fc540f6..a34693b7cb12 100644
|
||||
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||
@@ -5869,9 +5869,26 @@ public void setMimeGroup(String packageName, String mimeGroup, List<String> mime
|
||||
packageStateWrite.setMimeGroup(mimeGroup, mimeTypesSet);
|
||||
});
|
||||
if (mComponentResolver.updateMimeGroup(snapshotComputer(), packageName, mimeGroup)) {
|
||||
- Binder.withCleanCallingIdentity(() ->
|
||||
- mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
|
||||
- UserHandle.USER_ALL));
|
||||
+ Binder.withCleanCallingIdentity(() -> {
|
||||
+ mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
|
||||
+ 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();
|
@ -1,82 +0,0 @@
|
||||
From cb2db1244c4668fe8b3d6cf36d0078190fa8f0af Mon Sep 17 00:00:00 2001
|
||||
From: Bishoy Gendy <bishoygendy@google.com>
|
||||
Date: Thu, 11 Apr 2024 16:37:10 +0000
|
||||
Subject: [PATCH] Fix security vulnerability allowing apps to start from
|
||||
background
|
||||
|
||||
Bug: 317048338
|
||||
Test: Using the steps in b/317048338#comment12
|
||||
(cherry picked from commit c5fc8ea92c0aabbb2fdccc23b743c18a8bf62e64)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df3584bb93ab89d7e174f7d39e42d4b22cb92fe0)
|
||||
Merged-In: Ia91199fdb23beed27bde687fdca8fe5d3a5a4759
|
||||
Change-Id: Ia91199fdb23beed27bde687fdca8fe5d3a5a4759
|
||||
---
|
||||
.../media/session/ParcelableListBinder.java | 13 +++++++++++--
|
||||
.../android/server/media/MediaSessionRecord.java | 14 ++++++++------
|
||||
2 files changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/media/java/android/media/session/ParcelableListBinder.java b/media/java/android/media/session/ParcelableListBinder.java
|
||||
index bbf1e0889b68..d78828462b1e 100644
|
||||
--- a/media/java/android/media/session/ParcelableListBinder.java
|
||||
+++ b/media/java/android/media/session/ParcelableListBinder.java
|
||||
@@ -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 @@ protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
||||
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) {
|
||||
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
index b459cfe6b44e..8f07b3924da0 100644
|
||||
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
|
||||
@@ -1100,12 +1100,14 @@ public void resetQueue() throws RemoteException {
|
||||
|
||||
@Override
|
||||
public IBinder getBinderForSetQueue() throws RemoteException {
|
||||
- return new ParcelableListBinder<QueueItem>((list) -> {
|
||||
- synchronized (mLock) {
|
||||
- mQueue = list;
|
||||
- }
|
||||
- mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
|
||||
- });
|
||||
+ return new ParcelableListBinder<QueueItem>(
|
||||
+ QueueItem.class,
|
||||
+ (list) -> {
|
||||
+ synchronized (mLock) {
|
||||
+ mQueue = list;
|
||||
+ }
|
||||
+ mHandler.post(MessageHandler.MSG_UPDATE_QUEUE);
|
||||
+ });
|
||||
}
|
||||
|
||||
@Override
|
@ -1,37 +0,0 @@
|
||||
From 93a2c9a876b978db4109a5360479e793eba5bf95 Mon Sep 17 00:00:00 2001
|
||||
From: Yi-an Chen <theianchen@google.com>
|
||||
Date: Tue, 23 Apr 2024 21:17:44 +0000
|
||||
Subject: [PATCH] Fix security vulnerability of non-dynamic permission removal
|
||||
|
||||
The original removePermission() code in PermissionManagerServiceImpl
|
||||
missed a logical negation operator when handling non-dynamic
|
||||
permissions, causing both
|
||||
testPermissionPermission_nonDynamicPermission_permissionUnchanged and
|
||||
testRemovePermission_dynamicPermission_permissionRemoved tests in
|
||||
DynamicPermissionsTest to fail.
|
||||
|
||||
The corresponding test DynamicPermissionsTest is also updated in the
|
||||
other CL: ag/27073864
|
||||
|
||||
Bug: 321711213
|
||||
Test: DynamicPermissionsTest on sc-dev and tm-dev locally
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0ead58f69f5de82b00406316b333366d556239f1)
|
||||
Merged-In: Ia146d4098643d9c473f8c83d33a8a125a53101fc
|
||||
Change-Id: Ia146d4098643d9c473f8c83d33a8a125a53101fc
|
||||
---
|
||||
.../server/pm/permission/PermissionManagerServiceImpl.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
|
||||
index 1ec3403a9d46..3e06df908858 100644
|
||||
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
|
||||
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
|
||||
@@ -677,7 +677,7 @@ public void removePermission(String permName) {
|
||||
if (bp == null) {
|
||||
return;
|
||||
}
|
||||
- if (bp.isDynamic()) {
|
||||
+ if (!bp.isDynamic()) {
|
||||
// TODO: switch this back to SecurityException
|
||||
Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
|
||||
+ permName);
|
@ -1,176 +0,0 @@
|
||||
From ed52683e9c4960b21ff9d7a7c38bef5bfa02d4fb Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Coenen <maco@google.com>
|
||||
Date: Thu, 29 Feb 2024 12:03:05 +0000
|
||||
Subject: [PATCH] Verify UID of incoming Zygote connections.
|
||||
|
||||
Only the system UID should be allowed to connect to the Zygote. While
|
||||
for generic Zygotes this is also covered by SELinux policy, this is not
|
||||
true for App Zygotes: the preload code running in an app zygote could
|
||||
connect to another app zygote socket, if it had access to its (random)
|
||||
socket address.
|
||||
|
||||
On the Java layer, simply check the UID when the connection is made. In
|
||||
the native layer, this check was already present, but it actually didn't
|
||||
work in the case where we receive a new incoming connection on the
|
||||
socket, and receive a 'non-fork' command: in that case, we will simply
|
||||
exit the native loop, and let the Java layer handle the command, without
|
||||
any further UID checking.
|
||||
|
||||
Modified the native logic to drop new connections with a mismatching
|
||||
UID, and to keep serving the existing connection (if it was still
|
||||
there).
|
||||
|
||||
Bug: 319081336
|
||||
Test: manual
|
||||
(cherry picked from commit 2ffc7cb220e4220b7e108c4043a3f0f2a85b6508)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f1d4b34ad51b6ccb84ab042486923da8b2451e0f)
|
||||
Merged-In: I3f85a17107849e2cd3e82d6ef15c90b9e2f26532
|
||||
Change-Id: I3f85a17107849e2cd3e82d6ef15c90b9e2f26532
|
||||
---
|
||||
.../android/internal/os/ZygoteConnection.java | 3 +
|
||||
...ndroid_internal_os_ZygoteCommandBuffer.cpp | 82 ++++++++++++-------
|
||||
2 files changed, 56 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
index 252c0d08ac5a..3e0698d4564c 100644
|
||||
--- a/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
|
||||
@@ -94,6 +94,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;
|
||||
}
|
||||
|
||||
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
index 0b422122f03b..77e9bee9df5e 100644
|
||||
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
|
||||
@@ -367,6 +367,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.
|
||||
@@ -425,19 +437,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,
|
||||
@@ -467,30 +472,56 @@ 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));
|
||||
}
|
||||
- // 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));
|
||||
+ int new_fd = -1;
|
||||
+ do {
|
||||
+ // We've now seen either a disconnect or connect request.
|
||||
+ 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) {
|
||||
- fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
|
||||
+ // 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.
|
||||
- if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
|
||||
- fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
|
||||
- new_fd, session_socket, strerror(errno)));
|
||||
- }
|
||||
- close(new_fd); // On Linux, fd is closed even if EINTR is returned.
|
||||
+ // 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.
|
||||
+ if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
|
||||
+ fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
|
||||
+ new_fd, session_socket, strerror(errno)));
|
||||
+ }
|
||||
+ close(new_fd); // On Linux, fd is closed even if EINTR is returned.
|
||||
}
|
||||
// If we ever return, we effectively reuse the old Java ZygoteConnection.
|
||||
// None of its state needs to change.
|
||||
@@ -502,13 +533,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));
|
@ -1,51 +0,0 @@
|
||||
From ce7b9fd0f521cb6b038cb355b64f81f0c7524114 Mon Sep 17 00:00:00 2001
|
||||
From: Omar Eissa <oeissa@google.com>
|
||||
Date: Mon, 15 Apr 2024 12:04:56 +0000
|
||||
Subject: [PATCH] Prevent insertion in other users storage volumes
|
||||
|
||||
Don't allow file insertion in other users storage volumes.
|
||||
This was already handled if DATA was explicitly set in content values,
|
||||
but was allowed if DATA was generated based on other values like RELATIVE_PATH and DISPLAY_NAME.
|
||||
|
||||
Insertion of files in other users storage volumes can be used by malicious apps
|
||||
to get access to other users files, since the same file would exist in both users MP databases
|
||||
which would lead to MP falsely assuming that the user has access to this file.
|
||||
|
||||
Bug: 294406604
|
||||
Test: atest MediaProviderTests
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df39f8486b25473d0bdbeed896ad917e3c793bf9)
|
||||
Merged-In: Ie219bbdbe28819421040e4c083b65ab47d8ebde6
|
||||
Change-Id: Ie219bbdbe28819421040e4c083b65ab47d8ebde6
|
||||
---
|
||||
src/com/android/providers/media/MediaProvider.java | 1 +
|
||||
tests/src/com/android/providers/media/MediaProviderTest.java | 5 ++---
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
|
||||
index 8c1df561b..04167d911 100644
|
||||
--- a/src/com/android/providers/media/MediaProvider.java
|
||||
+++ b/src/com/android/providers/media/MediaProvider.java
|
||||
@@ -3891,6 +3891,7 @@ private void ensureFileColumns(int match, @NonNull Uri uri, @NonNull Bundle extr
|
||||
|
||||
FileUtils.sanitizeValues(values, /*rewriteHiddenFileName*/ !isFuseThread());
|
||||
FileUtils.computeDataFromValues(values, volumePath, isFuseThread());
|
||||
+ assertFileColumnsConsistent(match, uri, values);
|
||||
|
||||
// Create result file
|
||||
File res = new File(values.getAsString(MediaColumns.DATA));
|
||||
diff --git a/tests/src/com/android/providers/media/MediaProviderTest.java b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
index fc3029241..3bd86673c 100644
|
||||
--- a/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
+++ b/tests/src/com/android/providers/media/MediaProviderTest.java
|
||||
@@ -379,9 +379,8 @@ private void testActionLongFileNameItemHasTrimmedFileName(String columnKey) thro
|
||||
@Test
|
||||
public void testInsertionWithInvalidFilePath_throwsIllegalArgumentException() {
|
||||
final ContentValues values = new ContentValues();
|
||||
- values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Android/media/com.example");
|
||||
- values.put(MediaStore.Images.Media.DISPLAY_NAME,
|
||||
- "./../../../../../../../../../../../data/media/test.txt");
|
||||
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Android/media/com.example/");
|
||||
+ values.put(MediaStore.Images.Media.DISPLAY_NAME, "data/media/test.txt");
|
||||
|
||||
IllegalArgumentException illegalArgumentException = Assert.assertThrows(
|
||||
IllegalArgumentException.class, () -> sIsolatedResolver.insert(
|
@ -1,292 +0,0 @@
|
||||
From df49ae67f1baf3b8d3f5f0558a4512bea1e28b04 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Su <wengsu@google.com>
|
||||
Date: Wed, 3 Apr 2024 10:45:43 +0800
|
||||
Subject: [PATCH] [RESTRICT AUTOMERGE] Restrict WifiDppConfiguratorActivity
|
||||
|
||||
- Don't show WifiDppConfiguratorActivity if user has DISALLOW_ADD_WIFI_CONFIG
|
||||
|
||||
- Don't show AddNetworkFragment if user has DISALLOW_ADD_WIFI_CONFIG
|
||||
|
||||
Fix: 299931076
|
||||
Flag: None
|
||||
Test: manual test with TestDPC
|
||||
atest -c SettingsUnitTests:AddNetworkFragmentTest \
|
||||
SettingsUnitTests:WifiDppConfiguratorActivityTest
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:254ba087c29503e8bcf01cc10082c3f393e7701f)
|
||||
Merged-In: I34afe0f698e2dc43eba59b25f5f3f4f61e70166a
|
||||
Change-Id: I34afe0f698e2dc43eba59b25f5f3f4f61e70166a
|
||||
---
|
||||
.../settings/wifi/AddNetworkFragment.java | 20 +++++
|
||||
.../wifi/dpp/WifiDppConfiguratorActivity.java | 21 ++++++
|
||||
.../settings/wifi/AddNetworkFragmentTest.java | 74 +++++++++++++++++++
|
||||
.../dpp/WifiDppConfiguratorActivityTest.java | 74 +++++++++++++++++++
|
||||
4 files changed, 189 insertions(+)
|
||||
create mode 100644 tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
create mode 100644 tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
|
||||
diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
index 47a027d8bed..eb48d7d9aa2 100644
|
||||
--- a/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
+++ b/src/com/android/settings/wifi/AddNetworkFragment.java
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
+import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.os.Bundle;
|
||||
+import android.os.UserManager;
|
||||
+import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -41,6 +46,7 @@
|
||||
*/
|
||||
public class AddNetworkFragment extends InstrumentedFragment implements WifiConfigUiBase2,
|
||||
View.OnClickListener {
|
||||
+ private static final String TAG = "AddNetworkFragment";
|
||||
|
||||
public static final String WIFI_CONFIG_KEY = "wifi_config_key";
|
||||
@VisibleForTesting
|
||||
@@ -58,6 +64,10 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
+ if (!isAddWifiConfigAllowed(getContext())) {
|
||||
+ getActivity().finish();
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -209,4 +219,14 @@ void handleCancelAction() {
|
||||
activity.setResult(Activity.RESULT_CANCELED);
|
||||
activity.finish();
|
||||
}
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ static boolean isAddWifiConfigAllowed(Context context) {
|
||||
+ UserManager userManager = context.getSystemService(UserManager.class);
|
||||
+ if (userManager != null && userManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)) {
|
||||
+ Log.e(TAG, "The user is not allowed to add Wi-Fi configuration.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
index e6f0b31f384..d7444c8a42b 100644
|
||||
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.wifi.dpp;
|
||||
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -99,6 +101,10 @@ public int getMetricsCategory() {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
+ if (!isAddWifiConfigAllowed(getApplicationContext())) {
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
String qrCode = savedInstanceState.getString(KEY_QR_CODE);
|
||||
@@ -119,6 +125,11 @@ protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@Override
|
||||
protected void handleIntent(Intent intent) {
|
||||
+ if (!isAddWifiConfigAllowed(getApplicationContext())) {
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (isGuestUser(getApplicationContext())) {
|
||||
Log.e(TAG, "Guest user is not allowed to configure Wi-Fi!");
|
||||
EventLog.writeEvent(0x534e4554, "224772890", -1 /* UID */, "User is a guest");
|
||||
@@ -402,4 +413,14 @@ private static boolean isGuestUser(Context context) {
|
||||
if (userManager == null) return false;
|
||||
return userManager.isGuestUser();
|
||||
}
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ static boolean isAddWifiConfigAllowed(Context context) {
|
||||
+ UserManager userManager = context.getSystemService(UserManager.class);
|
||||
+ if (userManager != null && userManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)) {
|
||||
+ Log.e(TAG, "The user is not allowed to add Wi-Fi configuration.");
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java b/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
new file mode 100644
|
||||
index 00000000000..22d43c9bb4e
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/src/com/android/settings/wifi/AddNetworkFragmentTest.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 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.settings.wifi;
|
||||
+
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+
|
||||
+import androidx.test.annotation.UiThreadTest;
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+@UiThreadTest
|
||||
+public class AddNetworkFragmentTest {
|
||||
+
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ private AddNetworkFragment mFragment;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+
|
||||
+ mFragment = new AddNetworkFragment();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasNoUserRestriction_returnTrue() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
|
||||
+
|
||||
+ assertThat(mFragment.isAddWifiConfigAllowed(mContext)).isTrue();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasUserRestriction_returnFalse() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
|
||||
+
|
||||
+ assertThat(mFragment.isAddWifiConfigAllowed(mContext)).isFalse();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
new file mode 100644
|
||||
index 00000000000..4d723dc1846
|
||||
--- /dev/null
|
||||
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2024 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.settings.wifi.dpp;
|
||||
+
|
||||
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
|
||||
+
|
||||
+import static com.google.common.truth.Truth.assertThat;
|
||||
+
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.content.Context;
|
||||
+import android.os.UserManager;
|
||||
+
|
||||
+import androidx.test.annotation.UiThreadTest;
|
||||
+import androidx.test.core.app.ApplicationProvider;
|
||||
+import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
+
|
||||
+import org.junit.Before;
|
||||
+import org.junit.Rule;
|
||||
+import org.junit.Test;
|
||||
+import org.junit.runner.RunWith;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.Spy;
|
||||
+import org.mockito.junit.MockitoJUnit;
|
||||
+import org.mockito.junit.MockitoRule;
|
||||
+
|
||||
+@RunWith(AndroidJUnit4.class)
|
||||
+@UiThreadTest
|
||||
+public class WifiDppConfiguratorActivityTest {
|
||||
+
|
||||
+ @Rule
|
||||
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
+ @Spy
|
||||
+ private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ private WifiDppConfiguratorActivity mActivity;
|
||||
+
|
||||
+ @Before
|
||||
+ public void setUp() {
|
||||
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
+
|
||||
+ mActivity = new WifiDppConfiguratorActivity();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasNoUserRestriction_returnTrue() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
|
||||
+
|
||||
+ assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isTrue();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void isAddWifiConfigAllowed_hasUserRestriction_returnFalse() {
|
||||
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
|
||||
+
|
||||
+ assertThat(mActivity.isAddWifiConfigAllowed(mContext)).isFalse();
|
||||
+ }
|
||||
+}
|
@ -1,261 +0,0 @@
|
||||
From 09e63307961e3fa93d4bcb2ce73821e73b3bc8c4 Mon Sep 17 00:00:00 2001
|
||||
From: Vova Sharaienko <sharaienko@google.com>
|
||||
Date: Thu, 20 Jul 2023 23:25:31 +0000
|
||||
Subject: [PATCH] [statsd] Make executor thread a class member of
|
||||
MultiConditionTrigger
|
||||
|
||||
executorThread references class members after detaching. Making
|
||||
executorThread as class member and joining in MultiConditionTrigger
|
||||
destructor.
|
||||
|
||||
Ignore-AOSP-First: Security bugs merged into internal branch first
|
||||
Test: atest statsd_test
|
||||
Bug: 292160348
|
||||
Flag: NONE mainline module bug fix
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:262e2c8a5293483c98be498e60e1e5d15c6a0145)
|
||||
Merged-In: I7036eb3d506e8ca88e4a5faa6275dc4cba8020ee
|
||||
Change-Id: I7036eb3d506e8ca88e4a5faa6275dc4cba8020ee
|
||||
---
|
||||
statsd/src/utils/MultiConditionTrigger.cpp | 21 ++-
|
||||
statsd/src/utils/MultiConditionTrigger.h | 10 +-
|
||||
.../utils/MultiConditionTrigger_test.cpp | 121 ++++++++++++++++++
|
||||
3 files changed, 144 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/statsd/src/utils/MultiConditionTrigger.cpp b/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
index 5ef50ee09..5078cae6d 100644
|
||||
--- a/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
+++ b/statsd/src/utils/MultiConditionTrigger.cpp
|
||||
@@ -14,11 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define STATSD_DEBUG false // STOPSHIP if true
|
||||
+#include "Log.h"
|
||||
|
||||
#include "MultiConditionTrigger.h"
|
||||
|
||||
-#include <thread>
|
||||
-
|
||||
using namespace std;
|
||||
|
||||
namespace android {
|
||||
@@ -31,8 +30,7 @@ MultiConditionTrigger::MultiConditionTrigger(const set<string>& conditionNames,
|
||||
mTrigger(trigger),
|
||||
mCompleted(mRemainingConditionNames.empty()) {
|
||||
if (mCompleted) {
|
||||
- thread executorThread([this] { mTrigger(); });
|
||||
- executorThread.detach();
|
||||
+ startExecutorThread();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +46,21 @@ void MultiConditionTrigger::markComplete(const string& conditionName) {
|
||||
doTrigger = mCompleted;
|
||||
}
|
||||
if (doTrigger) {
|
||||
- std::thread executorThread([this] { mTrigger(); });
|
||||
- executorThread.detach();
|
||||
+ startExecutorThread();
|
||||
}
|
||||
}
|
||||
+
|
||||
+void MultiConditionTrigger::startExecutorThread() {
|
||||
+ mExecutorThread = make_unique<thread>([this] { mTrigger(); });
|
||||
+}
|
||||
+
|
||||
+MultiConditionTrigger::~MultiConditionTrigger() {
|
||||
+ if (mExecutorThread != nullptr && mExecutorThread->joinable()) {
|
||||
+ VLOG("MultiConditionTrigger waiting on execution thread termination");
|
||||
+ mExecutorThread->join();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
diff --git a/statsd/src/utils/MultiConditionTrigger.h b/statsd/src/utils/MultiConditionTrigger.h
|
||||
index 51f602991..dee007133 100644
|
||||
--- a/statsd/src/utils/MultiConditionTrigger.h
|
||||
+++ b/statsd/src/utils/MultiConditionTrigger.h
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
+#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
@@ -27,8 +28,8 @@ namespace statsd {
|
||||
/**
|
||||
* This class provides a utility to wait for a set of named conditions to occur.
|
||||
*
|
||||
- * It will execute the trigger runnable in a detached thread once all conditions have been marked
|
||||
- * true.
|
||||
+ * It will execute the trigger runnable in a separate thread (which will be joined at instance
|
||||
+ * destructor time) once all conditions have been marked true.
|
||||
*/
|
||||
class MultiConditionTrigger {
|
||||
public:
|
||||
@@ -37,19 +38,24 @@ class MultiConditionTrigger {
|
||||
|
||||
MultiConditionTrigger(const MultiConditionTrigger&) = delete;
|
||||
MultiConditionTrigger& operator=(const MultiConditionTrigger&) = delete;
|
||||
+ ~MultiConditionTrigger();
|
||||
|
||||
// Mark a specific condition as true. If this condition has called markComplete already or if
|
||||
// the event was not specified in the constructor, the function is a no-op.
|
||||
void markComplete(const std::string& eventName);
|
||||
|
||||
private:
|
||||
+ void startExecutorThread();
|
||||
+
|
||||
mutable std::mutex mMutex;
|
||||
std::set<std::string> mRemainingConditionNames;
|
||||
std::function<void()> mTrigger;
|
||||
bool mCompleted;
|
||||
+ std::unique_ptr<std::thread> mExecutorThread;
|
||||
|
||||
FRIEND_TEST(MultiConditionTriggerTest, TestCountDownCalledBySameEventName);
|
||||
};
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
diff --git a/statsd/tests/utils/MultiConditionTrigger_test.cpp b/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
index 32cecd3b9..b525f75e6 100644
|
||||
--- a/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
+++ b/statsd/tests/utils/MultiConditionTrigger_test.cpp
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
+#include "tests/statsd_test_util.h"
|
||||
+
|
||||
#ifdef __ANDROID__
|
||||
|
||||
using namespace std;
|
||||
@@ -166,6 +168,125 @@ TEST(MultiConditionTrigger, TestTriggerOnlyCalledOnce) {
|
||||
}
|
||||
}
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+class TriggerDependency {
|
||||
+public:
|
||||
+ TriggerDependency(mutex& lock, condition_variable& cv, bool& triggerCalled, int& triggerCount)
|
||||
+ : mLock(lock), mCv(cv), mTriggerCalled(triggerCalled), mTriggerCount(triggerCount) {
|
||||
+ }
|
||||
+
|
||||
+ void someMethod() {
|
||||
+ lock_guard lg(mLock);
|
||||
+ mTriggerCount++;
|
||||
+ mTriggerCalled = true;
|
||||
+ mCv.notify_all();
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ mutex& mLock;
|
||||
+ condition_variable& mCv;
|
||||
+ bool& mTriggerCalled;
|
||||
+ int& mTriggerCount;
|
||||
+};
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+TEST(MultiConditionTrigger, TestTriggerHasSleep) {
|
||||
+ const string t1 = "t1";
|
||||
+ set<string> conditionNames = {t1};
|
||||
+
|
||||
+ mutex lock;
|
||||
+ condition_variable cv;
|
||||
+ bool triggerCalled = false;
|
||||
+ int triggerCount = 0;
|
||||
+
|
||||
+ {
|
||||
+ TriggerDependency dependency(lock, cv, triggerCalled, triggerCount);
|
||||
+ MultiConditionTrigger trigger(conditionNames, [&dependency] {
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
+ dependency.someMethod();
|
||||
+ });
|
||||
+ trigger.markComplete(t1);
|
||||
+
|
||||
+ // Here dependency instance will go out of scope and the thread within MultiConditionTrigger
|
||||
+ // after delay will try to call method of already destroyed class instance
|
||||
+ // with leading crash if trigger execution thread is detached in MultiConditionTrigger
|
||||
+ // Instead since the MultiConditionTrigger destructor happens before TriggerDependency
|
||||
+ // destructor, MultiConditionTrigger destructor is waiting on execution thread termination
|
||||
+ // with thread::join
|
||||
+ }
|
||||
+ // At this moment the executor thread guaranteed terminated by MultiConditionTrigger destructor
|
||||
+
|
||||
+ // Ensure that the trigger fired.
|
||||
+ {
|
||||
+ unique_lock<mutex> unique_lk(lock);
|
||||
+ cv.wait(unique_lk, [&triggerCalled] { return triggerCalled; });
|
||||
+ EXPECT_TRUE(triggerCalled);
|
||||
+ EXPECT_EQ(triggerCount, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+TEST(MultiConditionTrigger, TestTriggerHasSleepEarlyTermination) {
|
||||
+ const string t1 = "t1";
|
||||
+ set<string> conditionNames = {t1};
|
||||
+
|
||||
+ mutex lock;
|
||||
+ condition_variable cv;
|
||||
+ bool triggerCalled = false;
|
||||
+ int triggerCount = 0;
|
||||
+
|
||||
+ std::condition_variable triggerTerminationFlag;
|
||||
+ std::mutex triggerTerminationFlagMutex;
|
||||
+ bool terminationRequested = false;
|
||||
+
|
||||
+ // used for error threshold tolerance due to wait_for() is involved
|
||||
+ const int64_t errorThresholdMs = 25;
|
||||
+ const int64_t triggerEarlyTerminationDelayMs = 100;
|
||||
+ const int64_t triggerStartNs = getElapsedRealtimeNs();
|
||||
+ {
|
||||
+ TriggerDependency dependency(lock, cv, triggerCalled, triggerCount);
|
||||
+ MultiConditionTrigger trigger(
|
||||
+ conditionNames, [&dependency, &triggerTerminationFlag, &triggerTerminationFlagMutex,
|
||||
+ &lock, &triggerCalled, &cv, &terminationRequested] {
|
||||
+ std::unique_lock<std::mutex> lk(triggerTerminationFlagMutex);
|
||||
+ if (triggerTerminationFlag.wait_for(
|
||||
+ lk, std::chrono::seconds(1),
|
||||
+ [&terminationRequested] { return terminationRequested; })) {
|
||||
+ // triggerTerminationFlag was notified - early termination is requested
|
||||
+ lock_guard lg(lock);
|
||||
+ triggerCalled = true;
|
||||
+ cv.notify_all();
|
||||
+ return;
|
||||
+ }
|
||||
+ dependency.someMethod();
|
||||
+ });
|
||||
+ trigger.markComplete(t1);
|
||||
+
|
||||
+ // notify to terminate trigger executor thread after triggerEarlyTerminationDelayMs
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(triggerEarlyTerminationDelayMs));
|
||||
+ {
|
||||
+ std::unique_lock<std::mutex> lk(triggerTerminationFlagMutex);
|
||||
+ terminationRequested = true;
|
||||
+ }
|
||||
+ triggerTerminationFlag.notify_all();
|
||||
+ }
|
||||
+ // At this moment the executor thread guaranteed terminated by MultiConditionTrigger destructor
|
||||
+
|
||||
+ // check that test duration is closer to 100ms rather to 1s
|
||||
+ const int64_t triggerEndNs = getElapsedRealtimeNs();
|
||||
+ EXPECT_LE(NanoToMillis(triggerEndNs - triggerStartNs),
|
||||
+ triggerEarlyTerminationDelayMs + errorThresholdMs);
|
||||
+
|
||||
+ // Ensure that the trigger fired but not the dependency.someMethod().
|
||||
+ {
|
||||
+ unique_lock<mutex> unique_lk(lock);
|
||||
+ cv.wait(unique_lk, [&triggerCalled] { return triggerCalled; });
|
||||
+ EXPECT_TRUE(triggerCalled);
|
||||
+ EXPECT_EQ(triggerCount, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
@ -66,8 +66,9 @@ patchWorkspaceReal() {
|
||||
verifyAllPlatformTags;
|
||||
gpgVerifyGitHead "$DOS_BUILD_BASE/external/chromium-webview";
|
||||
|
||||
#source build/envsetup.sh;
|
||||
source build/envsetup.sh;
|
||||
#repopick -ift twelve-bt-sbc-hd-dualchannel;
|
||||
repopick -it S_asb_2024-07;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -95,7 +95,6 @@ applyPatch "$DOS_PATCHES_COMMON/android_build/0001-verity-openssl3.patch"; #Fix
|
||||
sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
||||
awk -i inplace '!/updatable_apex.mk/' target/product/generic_system.mk; #Disable APEX
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
sed -i 's/2024-06-05/2024-07-05/' core/version_defaults.mk; #Bump Security String #X_asb_2024-07
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
@ -126,10 +125,6 @@ sed -i '11iLOCAL_OVERRIDES_PACKAGES := Camera Camera2 LegacyCamera Snap OpenCame
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/base"; then
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/329230490-1.patch"; #X_asb_2024-07 [CDM] Fix setSkipPrompt on Android S
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/397375.patch"; #T_asb_2024-07 Fix security vulnerability allowing apps to start from background
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/397376-backport.patch"; #T_asb_2024-07 Fix security vulnerability of non-dynamic permission removal
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/397377-backport.patch"; #T_asb_2024-07 Verify UID of incoming Zygote connections.
|
||||
git revert --no-edit 83fe523914728a3674debba17a6019cb74803045; #Reverts "Allow signature spoofing for microG Companion/Services" in favor of below patch
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/344888-backport.patch"; #fixup! fw/b: Add support for allowing/disallowing apps on cellular, vpn and wifi networks (CalyxOS)
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS)
|
||||
@ -304,7 +299,6 @@ fi;
|
||||
|
||||
if enterAndClear "packages/apps/Settings"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/316891059-19.patch"; #x-asb_2024-05 Replace getCallingActivity() with getLaunchedFromPackage()
|
||||
#applyPatch "$DOS_PATCHES/android_packages_apps_Settings/397378-backport.patch"; #T_asb_2024-07 Restrict WifiDppConfiguratorActivity
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0004-Private_DNS.patch"; #More 'Private DNS' options (heavily based off of a CalyxOS patch)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0005-Automatic_Reboot.patch"; #Timeout for reboot (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0006-Bluetooth_Timeout.patch"; #Timeout for Bluetooth (CalyxOS)
|
||||
@ -378,10 +372,6 @@ applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0005-Browser_No_Loc
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0006-Location_Indicators.patch"; #SystemUI: Use new privacy indicators for location (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/StatsD"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_StatsD/397380-backport.patch"; #T_asb_2024-07 Make executor thread a class member of MultiConditionTrigger
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Wifi"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Wifi/0001-Random_MAC.patch"; #Add support for always generating new random MAC (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Wifi/0001-Random_MAC-a1.patch"; #Fix MAC address leak after SSR (AOSP)
|
||||
@ -392,16 +382,11 @@ if enterAndClear "packages/providers/DownloadProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_DownloadProvider/0001-Network_Permission.patch"; #Expose the NETWORK permission (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/providers/MediaProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_MediaProvider/397381.patch"; #T_asb_2024-07 Prevent insertion in other users storage volumes
|
||||
fi
|
||||
|
||||
if enterAndClear "packages/services/Telephony"; then
|
||||
if [ -d "$DOS_BUILD_BASE"/vendor/divested-carriersettings ]; then applyPatch "$DOS_PATCHES/android_packages_services_Telephony/0001-CC2.patch"; fi; #Runtime control of platform carrier config package (DivestOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "system/bt"; then
|
||||
applyPatch "$DOS_PATCHES/android_system_bt/397379-backport.patch"; #T_asb_2024-07 Fix an authentication bypass bug in SMP
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_system_bt/0001-alloc_size.patch"; #Add alloc_size attributes to the allocator (GrapheneOS)
|
||||
fi;
|
||||
|
||||
|
@ -162,7 +162,8 @@ patchWorkspaceReal() {
|
||||
verifyAllPlatformTags;
|
||||
gpgVerifyGitHead "$DOS_BUILD_BASE/external/chromium-webview";
|
||||
|
||||
#source build/envsetup.sh;
|
||||
source build/envsetup.sh;
|
||||
repopick -it T_asb_2024-07;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -94,7 +94,6 @@ applyPatch "$DOS_PATCHES/android_build/0003-Exec_Based_Spawning.patch"; #Add exe
|
||||
applyPatch "$DOS_PATCHES/android_build/0004-Selective_APEX.patch"; #Only enable APEX on 6th/7th gen Pixel devices (GrapheneOS)
|
||||
sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_util.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
sed -i 's/2024-06-05/2024-07-05/' core/version_defaults.mk; #Bump Security String #X_asb_2024-07
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
@ -119,7 +118,6 @@ sed -i -e '76,78d;' Android.bp; #fix compile under A13
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/base"; then
|
||||
git am $DOS_PATCHES/ASB-2024-07/fwb-*.patch;
|
||||
git revert --no-edit d36faad3267522c6d3ff91ba9dcca8f6274bccd1; #Reverts "JobScheduler: Respect allow-in-power-save perm" in favor of below patch
|
||||
git revert --no-edit 90d6826548189ca850d91692e71fcc1be426f453; #Reverts "Remove sensitive info from SUPL requests" in favor of below patch
|
||||
git revert --no-edit 6d2955f0bd55e9938d5d49415182c27b50900b95; #Reverts "Allow signature spoofing for microG Companion/Services" in favor of below patch
|
||||
@ -307,7 +305,6 @@ applyPatch "$DOS_PATCHES/android_packages_apps_Nfc/0001-constify_JNINativeMethod
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/apps/Settings"; then
|
||||
git am $DOS_PATCHES/ASB-2024-07/settings-*.patch;
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/316891059-20.patch"; #x-asb_2024-05 Replace getCallingActivity() with getLaunchedFromPackage()
|
||||
git revert --no-edit 41b4ed345a91da1dd46c00ee11a151c2b5ff4f43;
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0004-Private_DNS.patch"; #More 'Private DNS' options (heavily based off of a CalyxOS patch)
|
||||
@ -357,10 +354,6 @@ applyPatch "$DOS_PATCHES/android_packages_inputmethods_LatinIME/0001-Voice.patch
|
||||
applyPatch "$DOS_PATCHES/android_packages_inputmethods_LatinIME/0002-Disable_Personalization.patch"; #Disable personalization dictionary by default (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Bluetooth"; then
|
||||
git am $DOS_PATCHES/ASB-2024-07/bluetooth-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Connectivity"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Connectivity/0001-Network_Permission-1.patch"; #Skip reportNetworkConnectivity() when permission is revoked (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Connectivity/0001-Network_Permission-2.patch"; #Enforce INTERNET permission per-uid instead of per-appId (GrapheneOS)
|
||||
@ -386,10 +379,6 @@ applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0005-Browser_No_Loc
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Permission/0006-Location_Indicators.patch"; #SystemUI: Use new privacy indicators for location (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/StatsD"; then
|
||||
git am $DOS_PATCHES/ASB-2024-07/statsd-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/modules/Wifi"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Wifi/344228.patch"; #wifi: resurrect mWifiLinkLayerStatsSupported counter (sassmann)
|
||||
applyPatch "$DOS_PATCHES/android_packages_modules_Wifi/0001-Random_MAC.patch"; #Add support for always generating new random MAC (GrapheneOS)
|
||||
@ -399,10 +388,6 @@ if enterAndClear "packages/providers/DownloadProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_DownloadProvider/0001-Network_Permission.patch"; #Expose the NETWORK permission (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/providers/MediaProvider"; then
|
||||
git am $DOS_PATCHES/ASB-2024-07/mediaprovider-*.patch;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/services/Telephony"; then
|
||||
if [ -d "$DOS_BUILD_BASE"/vendor/divested-carriersettings ]; then applyPatch "$DOS_PATCHES/android_packages_services_Telephony/0001-CC2.patch"; fi; #Runtime control of platform carrier config package (DivestOS)
|
||||
fi;
|
||||
|
Loading…
x
Reference in New Issue
Block a user