Cleaned up transaction sanitize calls
Exposed a way for a client to invoke sanitize with a uid and pid to
ensure we don't remove states when the process that added it was
privileged.
Added a helper function to get the permission ints based on the String
permission values so SF and clients can call the same API.
In SF, call sanitize as soon as setTransactionState is called since
that's the point where the Transaction has been passed over binder so we
can identify the calling uid. This allows us to remove the permission
values passed to applyTransactionState and unifies the places that were
calling sanitize.
Test: CredentialsTest
Bug: 267794530
Change-Id: I30c1800f0fee43df1cee82464139db7b56a7d911
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2d40678..95159d7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -110,6 +110,7 @@
#include <unordered_map>
#include <vector>
+#include <gui/LayerStatePermissions.h>
#include <ui/DisplayIdentification.h>
#include "BackgroundExecutor.h"
#include "Client.h"
@@ -4405,7 +4406,7 @@
transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
std::move(transaction.uncacheBufferIds), transaction.postTime,
- transaction.permissions, transaction.hasListenerCallbacks,
+ transaction.hasListenerCallbacks,
transaction.listenerCallbacks, transaction.originPid,
transaction.originUid, transaction.id);
}
@@ -4484,24 +4485,27 @@
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
- bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) {
+ InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp,
+ const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
- uint32_t permissions =
- callingThreadHasUnscopedSurfaceFlingerAccess() ?
- layer_state_t::Permission::ACCESS_SURFACE_FLINGER : 0;
- // Avoid checking for rotation permissions if the caller already has ACCESS_SURFACE_FLINGER
- // permissions.
- if ((permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) ||
- callingThreadHasPermission(sRotateSurfaceFlinger)) {
- permissions |= layer_state_t::Permission::ROTATE_SURFACE_FLINGER;
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
+ uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid);
+ for (auto composerState : states) {
+ composerState.state.sanitize(permissions);
}
- if (callingThreadHasPermission(sInternalSystemWindow)) {
- permissions |= layer_state_t::Permission::INTERNAL_SYSTEM_WINDOW;
+ for (DisplayState display : displays) {
+ display.sanitize(permissions);
+ }
+
+ if (!inputWindowCommands.empty() &&
+ (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) {
+ ALOGE("Only privileged callers are allowed to send input commands.");
+ inputWindowCommands.clear();
}
if (flags & (eEarlyWakeupStart | eEarlyWakeupEnd)) {
@@ -4517,10 +4521,6 @@
const int64_t postTime = systemTime();
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
std::vector<uint64_t> uncacheBufferIds;
uncacheBufferIds.reserve(uncacheBuffers.size());
for (const auto& uncacheBuffer : uncacheBuffers) {
@@ -4567,12 +4567,11 @@
displays,
flags,
applyToken,
- inputWindowCommands,
+ std::move(inputWindowCommands),
desiredPresentTime,
isAutoTimestamp,
std::move(uncacheBufferIds),
postTime,
- permissions,
hasListenerCallbacks,
listenerCallbacks,
originPid,
@@ -4601,14 +4600,12 @@
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, uint32_t permissions,
- bool hasListenerCallbacks,
+ const int64_t postTime, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
if (!mLayerLifecycleManagerEnabled) {
for (DisplayState& display : displays) {
- display.sanitize(permissions);
transactionFlags |= setDisplayStateLocked(display);
}
}
@@ -4625,12 +4622,12 @@
if (mLegacyFrontEndEnabled) {
clientStateFlags |=
setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime,
- isAutoTimestamp, postTime, permissions, transactionId);
+ isAutoTimestamp, postTime, transactionId);
} else /*mLayerLifecycleManagerEnabled*/ {
clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState,
desiredPresentTime, isAutoTimestamp,
- postTime, permissions, transactionId);
+ postTime, transactionId);
}
if ((flags & eAnimation) && resolvedState.state.surface) {
if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) {
@@ -4647,12 +4644,7 @@
}
transactionFlags |= clientStateFlags;
-
- if (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) {
- transactionFlags |= addInputWindowCommands(inputWindowCommands);
- } else if (!inputWindowCommands.empty()) {
- ALOGE("Only privileged callers are allowed to send input commands.");
- }
+ transactionFlags |= addInputWindowCommands(inputWindowCommands);
for (uint64_t uncacheBufferId : uncacheBufferIds) {
mBufferIdsToUncache.push_back(uncacheBufferId);
@@ -4689,7 +4681,6 @@
uint32_t transactionFlags = 0;
for (auto& transaction : transactions) {
for (DisplayState& display : transaction.displays) {
- display.sanitize(transaction.permissions);
transactionFlags |= setDisplayStateLocked(display);
}
}
@@ -4788,10 +4779,8 @@
uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo,
ResolvedComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions,
- uint64_t transactionId) {
+ int64_t postTime, uint64_t transactionId) {
layer_state_t& s = composerState.state;
- s.sanitize(permissions);
std::vector<ListenerCallbacks> filteredListeners;
for (auto& listener : s.listeners) {
@@ -5140,10 +5129,8 @@
ResolvedComposerState& composerState,
int64_t desiredPresentTime,
bool isAutoTimestamp, int64_t postTime,
- uint32_t permissions,
uint64_t transactionId) {
layer_state_t& s = composerState.state;
- s.sanitize(permissions);
std::vector<ListenerCallbacks> filteredListeners;
for (auto& listener : s.listeners) {
@@ -5425,7 +5412,6 @@
const nsecs_t now = systemTime();
state.desiredPresentTime = now;
state.postTime = now;
- state.permissions = layer_state_t::ACCESS_SURFACE_FLINGER;
state.originPid = mPid;
state.originUid = static_cast<int>(getuid());
const uint64_t transactionId = (static_cast<uint64_t>(mPid) << 32) | mUniqueTransactionId++;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8cc0184..cfaa221 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -510,7 +510,7 @@
status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
Vector<ComposerState>& state, const Vector<DisplayState>& displays,
uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands,
+ InputWindowCommands inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks,
@@ -731,14 +731,16 @@
/*
* Transactions
*/
- bool applyTransactionState(
- const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId) REQUIRES(mStateLock);
+ bool applyTransactionState(const FrameTimelineInfo& info,
+ std::vector<ResolvedComposerState>& state,
+ Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const std::vector<uint64_t>& uncacheBufferIds,
+ const int64_t postTime, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
// Flush pending transactions that were presented after desiredPresentTime.
// For test only
bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext);
@@ -759,12 +761,11 @@
uint32_t setClientStateLocked(const FrameTimelineInfo&, ResolvedComposerState&,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions, uint64_t transactionId)
- REQUIRES(mStateLock);
+ int64_t postTime, uint64_t transactionId) REQUIRES(mStateLock);
uint32_t updateLayerCallbacksAndStats(const FrameTimelineInfo&, ResolvedComposerState&,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t postTime, uint32_t permissions,
- uint64_t transactionId) REQUIRES(mStateLock);
+ int64_t postTime, uint64_t transactionId)
+ REQUIRES(mStateLock);
uint32_t getTransactionFlags() const;
// Sets the masked bits, and schedules a commit if needed.
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 35c8b6c..62a7dfd 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -54,7 +54,7 @@
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
int64_t desiredPresentTime, bool isAutoTimestamp,
- std::vector<uint64_t> uncacheBufferIds, int64_t postTime, uint32_t permissions,
+ std::vector<uint64_t> uncacheBufferIds, int64_t postTime,
bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
int originPid, int originUid, uint64_t transactionId)
: frameTimelineInfo(frameTimelineInfo),
@@ -67,7 +67,6 @@
isAutoTimestamp(isAutoTimestamp),
uncacheBufferIds(std::move(uncacheBufferIds)),
postTime(postTime),
- permissions(permissions),
hasListenerCallbacks(hasListenerCallbacks),
listenerCallbacks(listenerCallbacks),
originPid(originPid),
@@ -126,7 +125,6 @@
bool isAutoTimestamp;
std::vector<uint64_t> uncacheBufferIds;
int64_t postTime;
- uint32_t permissions;
bool hasListenerCallbacks;
std::vector<ListenerCallbacks> listenerCallbacks;
int originPid;
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 4a45eb5..69e9a16 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -31,6 +31,7 @@
#include <utils/String8.h>
#include <functional>
#include "utils/ScreenshotUtils.h"
+#include "utils/WindowInfosListenerUtils.h"
namespace android {
@@ -378,6 +379,58 @@
ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
}
+TEST_F(CredentialsTest, TransactionPermissionTest) {
+ WindowInfosListenerUtils windowInfosListenerUtils;
+ std::string name = "Test Layer";
+ sp<IBinder> token = sp<BBinder>::make();
+ WindowInfo windowInfo;
+ windowInfo.name = name;
+ windowInfo.token = token;
+ sp<SurfaceControl> surfaceControl =
+ mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState);
+ const Rect crop(0, 0, 100, 100);
+ {
+ UIDFaker f(AID_SYSTEM);
+ Transaction()
+ .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
+ .show(surfaceControl)
+ .setLayer(surfaceControl, INT32_MAX - 1)
+ .setCrop(surfaceControl, crop)
+ .setInputWindowInfo(surfaceControl, windowInfo)
+ .apply();
+ }
+
+ // Called from non privileged process
+ Transaction().setTrustedOverlay(surfaceControl, true);
+ {
+ UIDFaker f(AID_SYSTEM);
+ auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
+ auto foundWindowInfo =
+ WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ if (!foundWindowInfo) {
+ return false;
+ }
+ return !foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
+ };
+ windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted);
+ }
+
+ {
+ UIDFaker f(AID_SYSTEM);
+ Transaction().setTrustedOverlay(surfaceControl, true);
+ auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
+ auto foundWindowInfo =
+ WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ if (!foundWindowInfo) {
+ return false;
+ }
+ return foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
+ };
+ windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted);
+ }
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
index 3f27360..ad9a674 100644
--- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -20,11 +20,13 @@
#include <private/android_filesystem_config.h>
#include <cstdint>
#include <future>
+#include "utils/WindowInfosListenerUtils.h"
namespace android {
using Transaction = SurfaceComposerClient::Transaction;
using gui::DisplayInfo;
using gui::WindowInfo;
+constexpr auto findMatchingWindowInfo = WindowInfosListenerUtils::findMatchingWindowInfo;
using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>;
@@ -37,45 +39,14 @@
void TearDown() override { seteuid(AID_ROOT); }
- struct WindowInfosListener : public gui::WindowInfosListener {
- public:
- WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise)
- : mPredicate(std::move(predicate)), mPromise(promise) {}
-
- void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
- if (mPredicate(update.windowInfos)) {
- mPromise.set_value();
- }
- }
-
- private:
- WindowInfosPredicate mPredicate;
- std::promise<void>& mPromise;
- };
-
sp<SurfaceComposerClient> mClient;
+ WindowInfosListenerUtils mWindowInfosListenerUtils;
- bool waitForWindowInfosPredicate(WindowInfosPredicate predicate) {
- std::promise<void> promise;
- auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise);
- mClient->addWindowInfosListener(listener);
- auto future = promise.get_future();
- bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready;
- mClient->removeWindowInfosListener(listener);
- return satisfied;
+ bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) {
+ return mWindowInfosListenerUtils.waitForWindowInfosPredicate(std::move(predicate));
}
};
-const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo,
- const std::vector<WindowInfo>& windowInfos) {
- for (const WindowInfo& windowInfo : windowInfos) {
- if (windowInfo.token == targetWindowInfo.token) {
- return &windowInfo;
- }
- }
- return nullptr;
-}
-
TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
std::string name = "Test Layer";
sp<IBinder> token = sp<BBinder>::make();
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index dbb7c6c..6a641b3 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -386,7 +386,7 @@
transaction.applyToken,
transaction.inputWindowCommands,
transaction.desiredPresentTime,
- transaction.isAutoTimestamp, {}, systemTime(), 0,
+ transaction.isAutoTimestamp, {}, systemTime(),
mHasListenerCallbacks, mCallbacks, getpid(),
static_cast<int>(getuid()), transaction.id);
mFlinger.setTransactionStateInternal(transactionState);
diff --git a/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h
new file mode 100644
index 0000000..8e28a75
--- /dev/null
+++ b/services/surfaceflinger/tests/utils/WindowInfosListenerUtils.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/SurfaceComposerClient.h>
+#include <private/android_filesystem_config.h>
+#include <cstdint>
+#include <future>
+
+namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+using gui::DisplayInfo;
+using gui::WindowInfo;
+
+using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>;
+
+class WindowInfosListenerUtils {
+public:
+ WindowInfosListenerUtils() { mClient = sp<SurfaceComposerClient>::make(); }
+
+ bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) {
+ std::promise<void> promise;
+ auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise);
+ mClient->addWindowInfosListener(listener);
+ auto future = promise.get_future();
+ bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready;
+ mClient->removeWindowInfosListener(listener);
+ return satisfied;
+ }
+
+ static const WindowInfo* findMatchingWindowInfo(const WindowInfo& targetWindowInfo,
+ const std::vector<WindowInfo>& windowInfos) {
+ for (const WindowInfo& windowInfo : windowInfos) {
+ if (windowInfo.token == targetWindowInfo.token) {
+ return &windowInfo;
+ }
+ }
+ return nullptr;
+ }
+
+private:
+ struct WindowInfosListener : public gui::WindowInfosListener {
+ public:
+ WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise)
+ : mPredicate(std::move(predicate)), mPromise(promise) {}
+
+ void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
+ if (mPredicate(update.windowInfos)) {
+ mPromise.set_value();
+ }
+ }
+
+ private:
+ WindowInfosPredicate mPredicate;
+ std::promise<void>& mPromise;
+ };
+
+ sp<SurfaceComposerClient> mClient;
+};
+
+} // namespace android