diff options
| author | 2019-09-24 12:46:29 +0100 | |
|---|---|---|
| committer | 2019-10-02 15:32:49 -0500 | |
| commit | 7a522bf597fe680dd74b7fc0c8dfead2cd7fe781 (patch) | |
| tree | b3826f7b8d0eda58af97ec47384c1c5235815038 | |
| parent | 4d1b46c6e2d081539a510a4baf77f96e780d0e64 (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.bp | 1 | ||||
| -rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 43 |
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); |