summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Siarhei Vishniakou <svv@google.com> 2019-09-24 12:46:29 +0100
committer Siarhei Vishniakou <svv@google.com> 2019-10-02 15:32:49 -0500
commit7a522bf597fe680dd74b7fc0c8dfead2cd7fe781 (patch)
treeb3826f7b8d0eda58af97ec47384c1c5235815038
parent4d1b46c6e2d081539a510a4baf77f96e780d0e64 (diff)
Ensure input has CAP_BLOCK_SUSPEND
The process that's running the input code (currently, SYSTEM_SERVER) should be able to prevent suspend from happening. This is to make sure that we can always process the touch events. Since the kernel is not able to enforce the permissions for CAP_BLOCK_SUSPEND when EPOLLWAKEUP is being used, and just silently fails (see http://man7.org/linux/man-pages/man2/epoll_ctl.2.html and specifically the "BUGS" section), we should really make sure that the current process is able to hold the wakelock. Bug: 141532209 Test: boot up the phone and ensure it doesn't crash Change-Id: Ibde183cf7a41dd5369873093be373c10dd580115
-rw-r--r--services/inputflinger/reader/Android.bp1
-rw-r--r--services/inputflinger/reader/EventHub.cpp43
2 files changed, 44 insertions, 0 deletions
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index a64f4ddc47..3c1607096e 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -50,6 +50,7 @@ cc_library_shared {
shared_libs: [
"libbase",
+ "libcap",
"libinputflinger_base",
"libcrypto",
"libcutils",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index efe3809f1d..c8da0ab29f 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
@@ -237,6 +238,47 @@ bool EventHub::Device::hasValidFd() {
return !isVirtual && enabled;
}
+/**
+ * Get the capabilities for the current process.
+ * Crashes the system if unable to create / check / destroy the capabilities object.
+ */
+class Capabilities final {
+public:
+ explicit Capabilities() {
+ mCaps = cap_get_proc();
+ LOG_ALWAYS_FATAL_IF(mCaps == nullptr, "Could not get capabilities of the current process");
+ }
+
+ /**
+ * Check whether the current process has a specific capability
+ * in the set of effective capabilities.
+ * Return CAP_SET if the process has the requested capability
+ * Return CAP_CLEAR otherwise.
+ */
+ cap_flag_value_t checkEffectiveCapability(cap_value_t capability) {
+ cap_flag_value_t value;
+ const int result = cap_get_flag(mCaps, capability, CAP_EFFECTIVE, &value);
+ LOG_ALWAYS_FATAL_IF(result == -1, "Could not obtain the requested capability");
+ return value;
+ }
+
+ ~Capabilities() {
+ const int result = cap_free(mCaps);
+ LOG_ALWAYS_FATAL_IF(result == -1, "Could not release the capabilities structure");
+ }
+
+private:
+ cap_t mCaps;
+};
+
+static void ensureProcessCanBlockSuspend() {
+ Capabilities capabilities;
+ const bool canBlockSuspend =
+ capabilities.checkEffectiveCapability(CAP_BLOCK_SUSPEND) == CAP_SET;
+ LOG_ALWAYS_FATAL_IF(!canBlockSuspend,
+ "Input must be able to block suspend to properly process events");
+}
+
// --- EventHub ---
const int EventHub::EPOLL_MAX_EVENTS;
@@ -253,6 +295,7 @@ EventHub::EventHub(void)
mPendingEventCount(0),
mPendingEventIndex(0),
mPendingINotify(false) {
+ ensureProcessCanBlockSuspend();
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
mEpollFd = epoll_create1(EPOLL_CLOEXEC);