diff options
author | Greg Kaiser <gkaiser@google.com> | 2016-06-23 03:25:44 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-06-23 03:25:46 +0000 |
commit | c0ca0ceaa5a41094a23695a0f0511e96b297cdfa (patch) | |
tree | 9a13ab1e382269e7a5fe9721ab1a4aa726922ded | |
parent | ab69cc1f11a7e391bd3bb017a22ed747da89b21b (diff) | |
parent | 53ca2e00c6f2a71b93c8e3c8e85aeeb03c5bd06d (diff) | |
download | native-c0ca0ceaa5a41094a23695a0f0511e96b297cdfa.tar.gz |
Merge "Sensor: Make getId() more varied" into nyc-dev
-rw-r--r-- | include/gui/Sensor.h | 10 | ||||
-rw-r--r-- | libs/gui/Sensor.cpp | 22 | ||||
-rw-r--r-- | services/sensorservice/Android.mk | 3 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 134 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 11 |
5 files changed, 177 insertions, 3 deletions
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index 3f60741e47..094fd163bc 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -89,7 +89,14 @@ public: bool isDynamicSensor() const; bool hasAdditionalInfo() const; int32_t getReportingMode() const; + + // Note that after setId() has been called, getUuid() no longer + // returns the UUID. + // TODO(b/29547335): Remove getUuid(), add getUuidIndex(), and + // make sure setId() doesn't change the UuidIndex. const uuid_t& getUuid() const; + int32_t getId() const; + void setId(int32_t id); // LightFlattenable protocol inline bool isFixedSize() const { return false; } @@ -116,6 +123,9 @@ private: int32_t mRequiredAppOp; int32_t mMaxDelay; uint32_t mFlags; + // TODO(b/29547335): Get rid of this field and replace with an index. + // The index will be into a separate global vector of UUIDs. + // Also add an mId field (and change flatten/unflatten appropriately). uuid_t mUuid; static void flattenString8(void*& buffer, size_t& size, const String8& string8); static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8); diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index cc865d16dd..053d153296 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -408,6 +408,15 @@ const Sensor::uuid_t& Sensor::getUuid() const { return mUuid; } +void Sensor::setId(int32_t id) { + mUuid.i64[0] = id; + mUuid.i64[1] = 0; +} + +int32_t Sensor::getId() const { + return int32_t(mUuid.i64[0]); +} + size_t Sensor::getFlattenedSize() const { size_t fixedSize = sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) + @@ -448,7 +457,18 @@ status_t Sensor::flatten(void* buffer, size_t size) const { FlattenableUtils::write(buffer, size, mRequiredAppOp); FlattenableUtils::write(buffer, size, mMaxDelay); FlattenableUtils::write(buffer, size, mFlags); - FlattenableUtils::write(buffer, size, mUuid); + if (mUuid.i64[1] != 0) { + // We should never hit this case with our current API, but we + // could via a careless API change. If that happens, + // this code will keep us from leaking our UUID (while probably + // breaking dynamic sensors). See b/29547335. + ALOGW("Sensor with UUID being flattened; sending 0. Expect " + "bad dynamic sensor behavior"); + uuid_t tmpUuid; // default constructor makes this 0. + FlattenableUtils::write(buffer, size, tmpUuid); + } else { + FlattenableUtils::write(buffer, size, mUuid); + } return NO_ERROR; } diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk index 5a369613ae..7b10319e1b 100644 --- a/services/sensorservice/Android.mk +++ b/services/sensorservice/Android.mk @@ -34,7 +34,8 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libbinder \ libui \ - libgui + libgui \ + libcrypto LOCAL_MODULE:= libsensorservice diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 6caa85bff8..fb83effd25 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -26,6 +26,10 @@ #include <hardware/sensors.h> #include <hardware_legacy/power.h> +#include <openssl/digest.h> +#include <openssl/hmac.h> +#include <openssl/rand.h> + #include "BatteryService.h" #include "CorrectedGyroSensor.h" #include "GravitySensor.h" @@ -44,8 +48,10 @@ #include <inttypes.h> #include <math.h> #include <stdint.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> namespace android { // --------------------------------------------------------------------------- @@ -60,6 +66,12 @@ namespace android { */ const char* SensorService::WAKE_LOCK_NAME = "SensorService_wakelock"; +uint8_t SensorService::sHmacGlobalKey[128] = {}; +bool SensorService::sHmacGlobalKeyIsValid = false; + +#define SENSOR_SERVICE_DIR "/data/system/sensor_service" +#define SENSOR_SERVICE_HMAC_KEY_FILE SENSOR_SERVICE_DIR "/hmac_key" + // Permissions. static const String16 sDump("android.permission.DUMP"); @@ -68,10 +80,49 @@ SensorService::SensorService() mWakeLockAcquired(false) { } +bool SensorService::initializeHmacKey() { + int fd = open(SENSOR_SERVICE_HMAC_KEY_FILE, O_RDONLY|O_CLOEXEC); + if (fd != -1) { + int result = read(fd, sHmacGlobalKey, sizeof(sHmacGlobalKey)); + close(fd); + if (result == sizeof(sHmacGlobalKey)) { + return true; + } + ALOGW("Unable to read HMAC key; generating new one."); + } + + if (RAND_bytes(sHmacGlobalKey, sizeof(sHmacGlobalKey)) == -1) { + ALOGW("Can't generate HMAC key; dynamic sensor getId() will be wrong."); + return false; + } + + // We need to make sure this is only readable to us. + bool wroteKey = false; + mkdir(SENSOR_SERVICE_DIR, S_IRWXU); + fd = open(SENSOR_SERVICE_HMAC_KEY_FILE, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, + S_IRUSR|S_IWUSR); + if (fd != -1) { + int result = write(fd, sHmacGlobalKey, sizeof(sHmacGlobalKey)); + close(fd); + wroteKey = (result == sizeof(sHmacGlobalKey)); + } + if (wroteKey) { + ALOGI("Generated new HMAC key."); + } else { + ALOGW("Unable to write HMAC key; dynamic sensor getId() will change " + "after reboot."); + } + // Even if we failed to write the key we return true, because we did + // initialize the HMAC key. + return true; +} + void SensorService::onFirstRef() { ALOGD("nuSensorService starting..."); SensorDevice& dev(SensorDevice::getInstance()); + sHmacGlobalKeyIsValid = initializeHmacKey(); + if (dev.initCheck() == NO_ERROR) { sensor_t const* list; ssize_t count = dev.getSensorList(&list); @@ -719,6 +770,85 @@ bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const { return sensor != nullptr && sensor->getSensor().isWakeUpSensor(); } +int32_t SensorService::getIdFromUuid(const Sensor::uuid_t &uuid) const { + if ((uuid.i64[0] == 0) && (uuid.i64[1] == 0)) { + // UUID is not supported for this device. + return 0; + } + if ((uuid.i64[0] == INT64_C(~0)) && (uuid.i64[1] == INT64_C(~0))) { + // This sensor can be uniquely identified in the system by + // the combination of its type and name. + return -1; + } + + // We have a dynamic sensor. + + if (!sHmacGlobalKeyIsValid) { + // Rather than risk exposing UUIDs, we cripple dynamic sensors. + ALOGW("HMAC key failure; dynamic sensor getId() will be wrong."); + return 0; + } + + // We want each app author/publisher to get a different ID, so that the + // same dynamic sensor cannot be tracked across apps by multiple + // authors/publishers. So we use both our UUID and our User ID. + // Note potential confusion: + // UUID => Universally Unique Identifier. + // UID => User Identifier. + // We refrain from using "uid" except as needed by API to try to + // keep this distinction clear. + + auto appUserId = IPCThreadState::self()->getCallingUid(); + uint8_t uuidAndApp[sizeof(uuid) + sizeof(appUserId)]; + memcpy(uuidAndApp, &uuid, sizeof(uuid)); + memcpy(uuidAndApp + sizeof(uuid), &appUserId, sizeof(appUserId)); + + // Now we use our key on our UUID/app combo to get the hash. + uint8_t hash[EVP_MAX_MD_SIZE]; + unsigned int hashLen; + if (HMAC(EVP_sha256(), + sHmacGlobalKey, sizeof(sHmacGlobalKey), + uuidAndApp, sizeof(uuidAndApp), + hash, &hashLen) == nullptr) { + // Rather than risk exposing UUIDs, we cripple dynamic sensors. + ALOGW("HMAC failure; dynamic sensor getId() will be wrong."); + return 0; + } + + int32_t id = 0; + if (hashLen < sizeof(id)) { + // We never expect this case, but out of paranoia, we handle it. + // Our 'id' length is already quite small, we don't want the + // effective length of it to be even smaller. + // Rather than risk exposing UUIDs, we cripple dynamic sensors. + ALOGW("HMAC insufficient; dynamic sensor getId() will be wrong."); + return 0; + } + + // This is almost certainly less than all of 'hash', but it's as secure + // as we can be with our current 'id' length. + memcpy(&id, hash, sizeof(id)); + + // Note at the beginning of the function that we return the values of + // 0 and -1 to represent special cases. As a result, we can't return + // those as dynamic sensor IDs. If we happened to hash to one of those + // values, we change 'id' so we report as a dynamic sensor, and not as + // one of those special cases. + if (id == -1) { + id = -2; + } else if (id == 0) { + id = 1; + } + return id; +} + +void SensorService::makeUuidsIntoIdsForSensorList(Vector<Sensor> &sensorList) const { + for (auto &sensor : sensorList) { + int32_t id = getIdFromUuid(sensor.getUuid()); + sensor.setId(id); + } +} + Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); @@ -736,6 +866,7 @@ Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) { sensor.getRequiredAppOp()); } } + makeUuidsIntoIdsForSensorList(accessibleSensorList); return accessibleSensorList; } @@ -755,6 +886,7 @@ Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName } return true; }); + makeUuidsIntoIdsForSensorList(accessibleSensorList); return accessibleSensorList; } diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 0d04478083..c8de62190f 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -208,6 +208,17 @@ private: status_t resetToNormalMode(); status_t resetToNormalModeLocked(); + // Transforms the UUIDs for all the sensors into proper IDs. + void makeUuidsIntoIdsForSensorList(Vector<Sensor> &sensorList) const; + // Gets the appropriate ID from the given UUID. + int32_t getIdFromUuid(const Sensor::uuid_t &uuid) const; + // Either read from storage or create a new one. + static bool initializeHmacKey(); + + + static uint8_t sHmacGlobalKey[128]; + static bool sHmacGlobalKeyIsValid; + SensorList mSensors; status_t mInitCheck; |