summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kaiser <gkaiser@google.com>2016-06-23 03:25:44 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-06-23 03:25:46 +0000
commitc0ca0ceaa5a41094a23695a0f0511e96b297cdfa (patch)
tree9a13ab1e382269e7a5fe9721ab1a4aa726922ded
parentab69cc1f11a7e391bd3bb017a22ed747da89b21b (diff)
parent53ca2e00c6f2a71b93c8e3c8e85aeeb03c5bd06d (diff)
downloadnative-c0ca0ceaa5a41094a23695a0f0511e96b297cdfa.tar.gz
Merge "Sensor: Make getId() more varied" into nyc-dev
-rw-r--r--include/gui/Sensor.h10
-rw-r--r--libs/gui/Sensor.cpp22
-rw-r--r--services/sensorservice/Android.mk3
-rw-r--r--services/sensorservice/SensorService.cpp134
-rw-r--r--services/sensorservice/SensorService.h11
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;