修訂 | 4f0301652275eead25c0f9705af3c0b2745bd6fe (tree) |
---|---|
時間 | 2019-10-16 23:52:29 |
作者 | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
Merge tag 'android-7.1.2_r39' into nougat-x86
Android 7.1.2 Release 39 (5787804)
@@ -375,6 +375,7 @@ private: | ||
375 | 375 | void freeDataNoInit(); |
376 | 376 | void initState(); |
377 | 377 | void scanForFds() const; |
378 | + status_t validateReadData(size_t len) const; | |
378 | 379 | |
379 | 380 | template<class T> |
380 | 381 | status_t readAligned(T *pArg) const; |
@@ -421,6 +422,7 @@ private: | ||
421 | 422 | size_t mObjectsSize; |
422 | 423 | size_t mObjectsCapacity; |
423 | 424 | mutable size_t mNextObjectHint; |
425 | + mutable bool mObjectsSorted; | |
424 | 426 | |
425 | 427 | mutable bool mFdsKnown; |
426 | 428 | mutable bool mHasFds; |
@@ -42,6 +42,13 @@ namespace android { | ||
42 | 42 | * |
43 | 43 | * Note that this structure is used for IPCs so its layout must be identical |
44 | 44 | * on 64 and 32 bit processes. This is tested in StructLayout_test.cpp. |
45 | + * | |
46 | + * Since the struct must be aligned to an 8-byte boundary, there could be uninitialized bytes | |
47 | + * in-between the defined fields. This padding data should be explicitly accounted for by adding | |
48 | + * "empty" fields into the struct. This data is memset to zero before sending the struct across | |
49 | + * the socket. Adding the explicit fields ensures that the memset is not optimized away by the | |
50 | + * compiler. When a new field is added to the struct, the corresponding change | |
51 | + * in StructLayout_test should be made. | |
45 | 52 | */ |
46 | 53 | struct InputMessage { |
47 | 54 | enum { |
@@ -62,6 +69,7 @@ struct InputMessage { | ||
62 | 69 | union Body { |
63 | 70 | struct Key { |
64 | 71 | uint32_t seq; |
72 | + uint32_t empty1; | |
65 | 73 | nsecs_t eventTime __attribute__((aligned(8))); |
66 | 74 | int32_t deviceId; |
67 | 75 | int32_t source; |
@@ -80,6 +88,7 @@ struct InputMessage { | ||
80 | 88 | |
81 | 89 | struct Motion { |
82 | 90 | uint32_t seq; |
91 | + uint32_t empty1; | |
83 | 92 | nsecs_t eventTime __attribute__((aligned(8))); |
84 | 93 | int32_t deviceId; |
85 | 94 | int32_t source; |
@@ -95,6 +104,7 @@ struct InputMessage { | ||
95 | 104 | float xPrecision; |
96 | 105 | float yPrecision; |
97 | 106 | uint32_t pointerCount; |
107 | + uint32_t empty2; | |
98 | 108 | // Note that PointerCoords requires 8 byte alignment. |
99 | 109 | struct Pointer { |
100 | 110 | PointerProperties properties; |
@@ -125,6 +135,7 @@ struct InputMessage { | ||
125 | 135 | |
126 | 136 | bool isValid(size_t actualSize) const; |
127 | 137 | size_t size() const; |
138 | + void getSanitizedCopy(InputMessage* msg) const; | |
128 | 139 | }; |
129 | 140 | |
130 | 141 | /* |
@@ -459,6 +459,7 @@ void Parcel::setDataPosition(size_t pos) const | ||
459 | 459 | |
460 | 460 | mDataPos = pos; |
461 | 461 | mNextObjectHint = 0; |
462 | + mObjectsSorted = false; | |
462 | 463 | } |
463 | 464 | |
464 | 465 | status_t Parcel::setDataCapacity(size_t size) |
@@ -1284,7 +1285,7 @@ status_t Parcel::write(const FlattenableHelperInterface& val) | ||
1284 | 1285 | if (err) return err; |
1285 | 1286 | |
1286 | 1287 | // payload |
1287 | - void* const buf = this->writeInplace(pad_size(len)); | |
1288 | + void* const buf = this->writeInplace(len); | |
1288 | 1289 | if (buf == NULL) |
1289 | 1290 | return BAD_VALUE; |
1290 | 1291 |
@@ -1363,6 +1364,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/) | ||
1363 | 1364 | LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); |
1364 | 1365 | } |
1365 | 1366 | |
1367 | +status_t Parcel::validateReadData(size_t upperBound) const | |
1368 | +{ | |
1369 | + // Don't allow non-object reads on object data | |
1370 | + if (mObjectsSorted || mObjectsSize <= 1) { | |
1371 | +data_sorted: | |
1372 | + // Expect to check only against the next object | |
1373 | + if (mNextObjectHint < mObjectsSize && upperBound > mObjects[mNextObjectHint]) { | |
1374 | + // For some reason the current read position is greater than the next object | |
1375 | + // hint. Iterate until we find the right object | |
1376 | + size_t nextObject = mNextObjectHint; | |
1377 | + do { | |
1378 | + if (mDataPos < mObjects[nextObject] + sizeof(flat_binder_object)) { | |
1379 | + // Requested info overlaps with an object | |
1380 | + ALOGE("Attempt to read from protected data in Parcel %p", this); | |
1381 | + return PERMISSION_DENIED; | |
1382 | + } | |
1383 | + nextObject++; | |
1384 | + } while (nextObject < mObjectsSize && upperBound > mObjects[nextObject]); | |
1385 | + mNextObjectHint = nextObject; | |
1386 | + } | |
1387 | + return NO_ERROR; | |
1388 | + } | |
1389 | + // Quickly determine if mObjects is sorted. | |
1390 | + binder_size_t* currObj = mObjects + mObjectsSize - 1; | |
1391 | + binder_size_t* prevObj = currObj; | |
1392 | + while (currObj > mObjects) { | |
1393 | + prevObj--; | |
1394 | + if(*prevObj > *currObj) { | |
1395 | + goto data_unsorted; | |
1396 | + } | |
1397 | + currObj--; | |
1398 | + } | |
1399 | + mObjectsSorted = true; | |
1400 | + goto data_sorted; | |
1401 | + | |
1402 | +data_unsorted: | |
1403 | + // Insertion Sort mObjects | |
1404 | + // Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common, | |
1405 | + // switch to std::sort(mObjects, mObjects + mObjectsSize); | |
1406 | + for (binder_size_t* iter0 = mObjects + 1; iter0 < mObjects + mObjectsSize; iter0++) { | |
1407 | + binder_size_t temp = *iter0; | |
1408 | + binder_size_t* iter1 = iter0 - 1; | |
1409 | + while (iter1 >= mObjects && *iter1 > temp) { | |
1410 | + *(iter1 + 1) = *iter1; | |
1411 | + iter1--; | |
1412 | + } | |
1413 | + *(iter1 + 1) = temp; | |
1414 | + } | |
1415 | + mNextObjectHint = 0; | |
1416 | + mObjectsSorted = true; | |
1417 | + goto data_sorted; | |
1418 | +} | |
1419 | + | |
1366 | 1420 | status_t Parcel::read(void* outData, size_t len) const |
1367 | 1421 | { |
1368 | 1422 | if (len > INT32_MAX) { |
@@ -1373,6 +1427,15 @@ status_t Parcel::read(void* outData, size_t len) const | ||
1373 | 1427 | |
1374 | 1428 | if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize |
1375 | 1429 | && len <= pad_size(len)) { |
1430 | + if (mObjectsSize > 0) { | |
1431 | + status_t err = validateReadData(mDataPos + pad_size(len)); | |
1432 | + if(err != NO_ERROR) { | |
1433 | + // Still increment the data position by the expected length | |
1434 | + mDataPos += pad_size(len); | |
1435 | + ALOGV("read Setting data pos of %p to %zu", this, mDataPos); | |
1436 | + return err; | |
1437 | + } | |
1438 | + } | |
1376 | 1439 | memcpy(outData, mData+mDataPos, len); |
1377 | 1440 | mDataPos += pad_size(len); |
1378 | 1441 | ALOGV("read Setting data pos of %p to %zu", this, mDataPos); |
@@ -1391,6 +1454,16 @@ const void* Parcel::readInplace(size_t len) const | ||
1391 | 1454 | |
1392 | 1455 | if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize |
1393 | 1456 | && len <= pad_size(len)) { |
1457 | + if (mObjectsSize > 0) { | |
1458 | + status_t err = validateReadData(mDataPos + pad_size(len)); | |
1459 | + if(err != NO_ERROR) { | |
1460 | + // Still increment the data position by the expected length | |
1461 | + mDataPos += pad_size(len); | |
1462 | + ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); | |
1463 | + return NULL; | |
1464 | + } | |
1465 | + } | |
1466 | + | |
1394 | 1467 | const void* data = mData+mDataPos; |
1395 | 1468 | mDataPos += pad_size(len); |
1396 | 1469 | ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); |
@@ -1404,6 +1477,15 @@ status_t Parcel::readAligned(T *pArg) const { | ||
1404 | 1477 | COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); |
1405 | 1478 | |
1406 | 1479 | if ((mDataPos+sizeof(T)) <= mDataSize) { |
1480 | + if (mObjectsSize > 0) { | |
1481 | + status_t err = validateReadData(mDataPos + sizeof(T)); | |
1482 | + if(err != NO_ERROR) { | |
1483 | + // Still increment the data position by the expected length | |
1484 | + mDataPos += sizeof(T); | |
1485 | + return err; | |
1486 | + } | |
1487 | + } | |
1488 | + | |
1407 | 1489 | const void* data = mData+mDataPos; |
1408 | 1490 | mDataPos += sizeof(T); |
1409 | 1491 | *pArg = *reinterpret_cast<const T*>(data); |
@@ -1825,8 +1907,8 @@ status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { | ||
1825 | 1907 | |
1826 | 1908 | const char* Parcel::readCString() const |
1827 | 1909 | { |
1828 | - const size_t avail = mDataSize-mDataPos; | |
1829 | - if (avail > 0) { | |
1910 | + if (mDataPos < mDataSize) { | |
1911 | + const size_t avail = mDataSize-mDataPos; | |
1830 | 1912 | const char* str = reinterpret_cast<const char*>(mData+mDataPos); |
1831 | 1913 | // is the string's trailing NUL within the parcel's valid bounds? |
1832 | 1914 | const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail)); |
@@ -2206,6 +2288,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, | ||
2206 | 2288 | mObjects = const_cast<binder_size_t*>(objects); |
2207 | 2289 | mObjectsSize = mObjectsCapacity = objectsCount; |
2208 | 2290 | mNextObjectHint = 0; |
2291 | + mObjectsSorted = false; | |
2209 | 2292 | mOwner = relFunc; |
2210 | 2293 | mOwnerCookie = relCookie; |
2211 | 2294 | for (size_t i = 0; i < mObjectsSize; i++) { |
@@ -2364,6 +2447,7 @@ status_t Parcel::restartWrite(size_t desired) | ||
2364 | 2447 | mObjects = NULL; |
2365 | 2448 | mObjectsSize = mObjectsCapacity = 0; |
2366 | 2449 | mNextObjectHint = 0; |
2450 | + mObjectsSorted = false; | |
2367 | 2451 | mHasFds = false; |
2368 | 2452 | mFdsKnown = true; |
2369 | 2453 | mAllowFds = true; |
@@ -2450,6 +2534,7 @@ status_t Parcel::continueWrite(size_t desired) | ||
2450 | 2534 | mDataCapacity = desired; |
2451 | 2535 | mObjectsSize = mObjectsCapacity = objectsSize; |
2452 | 2536 | mNextObjectHint = 0; |
2537 | + mObjectsSorted = false; | |
2453 | 2538 | |
2454 | 2539 | } else if (mData) { |
2455 | 2540 | if (objectsSize < mObjectsSize) { |
@@ -2464,13 +2549,20 @@ status_t Parcel::continueWrite(size_t desired) | ||
2464 | 2549 | } |
2465 | 2550 | release_object(proc, *flat, this, &mOpenAshmemSize); |
2466 | 2551 | } |
2467 | - binder_size_t* objects = | |
2468 | - (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t)); | |
2469 | - if (objects) { | |
2470 | - mObjects = objects; | |
2552 | + | |
2553 | + if (objectsSize == 0) { | |
2554 | + free(mObjects); | |
2555 | + mObjects = nullptr; | |
2556 | + } else { | |
2557 | + binder_size_t* objects = | |
2558 | + (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t)); | |
2559 | + if (objects) { | |
2560 | + mObjects = objects; | |
2561 | + } | |
2471 | 2562 | } |
2472 | 2563 | mObjectsSize = objectsSize; |
2473 | 2564 | mNextObjectHint = 0; |
2565 | + mObjectsSorted = false; | |
2474 | 2566 | } |
2475 | 2567 | |
2476 | 2568 | // We own the data, so we can just do a realloc(). |
@@ -2543,6 +2635,7 @@ void Parcel::initState() | ||
2543 | 2635 | mObjectsSize = 0; |
2544 | 2636 | mObjectsCapacity = 0; |
2545 | 2637 | mNextObjectHint = 0; |
2638 | + mObjectsSorted = false; | |
2546 | 2639 | mHasFds = false; |
2547 | 2640 | mFdsKnown = true; |
2548 | 2641 | mAllowFds = true; |
@@ -66,13 +66,22 @@ status_t Status::readFromParcel(const Parcel& parcel) { | ||
66 | 66 | // Skip over fat response headers. Not used (or propagated) in native code. |
67 | 67 | if (mException == EX_HAS_REPLY_HEADER) { |
68 | 68 | // Note that the header size includes the 4 byte size field. |
69 | - const int32_t header_start = parcel.dataPosition(); | |
69 | + const size_t header_start = parcel.dataPosition(); | |
70 | + const size_t header_avail = parcel.dataAvail(); | |
71 | + | |
70 | 72 | int32_t header_size; |
71 | 73 | status = parcel.readInt32(&header_size); |
72 | 74 | if (status != OK) { |
73 | 75 | setFromStatusT(status); |
74 | 76 | return status; |
75 | 77 | } |
78 | + | |
79 | + if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) { | |
80 | + android_errorWriteLog(0x534e4554, "132650049"); | |
81 | + setFromStatusT(UNKNOWN_ERROR); | |
82 | + return UNKNOWN_ERROR; | |
83 | + } | |
84 | + | |
76 | 85 | parcel.setDataPosition(header_start + header_size); |
77 | 86 | // And fat response headers are currently only used when there are no |
78 | 87 | // exceptions, so act like there was no error. |
@@ -95,6 +104,7 @@ status_t Status::readFromParcel(const Parcel& parcel) { | ||
95 | 104 | if (mException == EX_SERVICE_SPECIFIC) { |
96 | 105 | status = parcel.readInt32(&mErrorCode); |
97 | 106 | } |
107 | + | |
98 | 108 | if (status != OK) { |
99 | 109 | setFromStatusT(status); |
100 | 110 | return status; |
@@ -90,7 +90,7 @@ SensorManager& SensorManager::getInstanceForPackage(const String16& packageName) | ||
90 | 90 | |
91 | 91 | SensorManager::SensorManager(const String16& opPackageName) |
92 | 92 | : mSensorList(0), mOpPackageName(opPackageName) { |
93 | - // okay we're not locked here, but it's not needed during construction | |
93 | + Mutex::Autolock _l(mLock); | |
94 | 94 | assertStateLocked(); |
95 | 95 | } |
96 | 96 |
@@ -97,6 +97,102 @@ size_t InputMessage::size() const { | ||
97 | 97 | return sizeof(Header); |
98 | 98 | } |
99 | 99 | |
100 | +/** | |
101 | + * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire | |
102 | + * memory to zero, then only copy the valid bytes on a per-field basis. | |
103 | + */ | |
104 | +void InputMessage::getSanitizedCopy(InputMessage* msg) const { | |
105 | + memset(msg, 0, sizeof(*msg)); | |
106 | + | |
107 | + // Write the header | |
108 | + msg->header.type = header.type; | |
109 | + | |
110 | + // Write the body | |
111 | + switch(header.type) { | |
112 | + case InputMessage::TYPE_KEY: { | |
113 | + // uint32_t seq | |
114 | + msg->body.key.seq = body.key.seq; | |
115 | + // nsecs_t eventTime | |
116 | + msg->body.key.eventTime = body.key.eventTime; | |
117 | + // int32_t deviceId | |
118 | + msg->body.key.deviceId = body.key.deviceId; | |
119 | + // int32_t source | |
120 | + msg->body.key.source = body.key.source; | |
121 | + // int32_t action | |
122 | + msg->body.key.action = body.key.action; | |
123 | + // int32_t flags | |
124 | + msg->body.key.flags = body.key.flags; | |
125 | + // int32_t keyCode | |
126 | + msg->body.key.keyCode = body.key.keyCode; | |
127 | + // int32_t scanCode | |
128 | + msg->body.key.scanCode = body.key.scanCode; | |
129 | + // int32_t metaState | |
130 | + msg->body.key.metaState = body.key.metaState; | |
131 | + // int32_t repeatCount | |
132 | + msg->body.key.repeatCount = body.key.repeatCount; | |
133 | + // nsecs_t downTime | |
134 | + msg->body.key.downTime = body.key.downTime; | |
135 | + break; | |
136 | + } | |
137 | + case InputMessage::TYPE_MOTION: { | |
138 | + // uint32_t seq | |
139 | + msg->body.motion.seq = body.motion.seq; | |
140 | + // nsecs_t eventTime | |
141 | + msg->body.motion.eventTime = body.motion.eventTime; | |
142 | + // int32_t deviceId | |
143 | + msg->body.motion.deviceId = body.motion.deviceId; | |
144 | + // int32_t source | |
145 | + msg->body.motion.source = body.motion.source; | |
146 | + // int32_t action | |
147 | + msg->body.motion.action = body.motion.action; | |
148 | + // int32_t actionButton | |
149 | + msg->body.motion.actionButton = body.motion.actionButton; | |
150 | + // int32_t flags | |
151 | + msg->body.motion.flags = body.motion.flags; | |
152 | + // int32_t metaState | |
153 | + msg->body.motion.metaState = body.motion.metaState; | |
154 | + // int32_t buttonState | |
155 | + msg->body.motion.buttonState = body.motion.buttonState; | |
156 | + // int32_t edgeFlags | |
157 | + msg->body.motion.edgeFlags = body.motion.edgeFlags; | |
158 | + // nsecs_t downTime | |
159 | + msg->body.motion.downTime = body.motion.downTime; | |
160 | + // float xOffset | |
161 | + msg->body.motion.xOffset = body.motion.xOffset; | |
162 | + // float yOffset | |
163 | + msg->body.motion.yOffset = body.motion.yOffset; | |
164 | + // float xPrecision | |
165 | + msg->body.motion.xPrecision = body.motion.xPrecision; | |
166 | + // float yPrecision | |
167 | + msg->body.motion.yPrecision = body.motion.yPrecision; | |
168 | + // uint32_t pointerCount | |
169 | + msg->body.motion.pointerCount = body.motion.pointerCount; | |
170 | + //struct Pointer pointers[MAX_POINTERS] | |
171 | + for (size_t i = 0; i < body.motion.pointerCount; i++) { | |
172 | + // PointerProperties properties | |
173 | + msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id; | |
174 | + msg->body.motion.pointers[i].properties.toolType = | |
175 | + body.motion.pointers[i].properties.toolType, | |
176 | + // PointerCoords coords | |
177 | + msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits; | |
178 | + const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits); | |
179 | + memcpy(&msg->body.motion.pointers[i].coords.values[0], | |
180 | + &body.motion.pointers[i].coords.values[0], | |
181 | + count * (sizeof(body.motion.pointers[i].coords.values[0]))); | |
182 | + } | |
183 | + break; | |
184 | + } | |
185 | + case InputMessage::TYPE_FINISHED: { | |
186 | + msg->body.finished.seq = body.finished.seq; | |
187 | + msg->body.finished.handled = body.finished.handled; | |
188 | + break; | |
189 | + } | |
190 | + default: { | |
191 | + LOG_FATAL("Unexpected message type %i", header.type); | |
192 | + break; | |
193 | + } | |
194 | + } | |
195 | +} | |
100 | 196 | |
101 | 197 | // --- InputChannel --- |
102 | 198 |
@@ -150,10 +246,12 @@ status_t InputChannel::openInputChannelPair(const String8& name, | ||
150 | 246 | } |
151 | 247 | |
152 | 248 | status_t InputChannel::sendMessage(const InputMessage* msg) { |
153 | - size_t msgLength = msg->size(); | |
249 | + const size_t msgLength = msg->size(); | |
250 | + InputMessage cleanMsg; | |
251 | + msg->getSanitizedCopy(&cleanMsg); | |
154 | 252 | ssize_t nWrite; |
155 | 253 | do { |
156 | - nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); | |
254 | + nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); | |
157 | 255 | } while (nWrite == -1 && errno == EINTR); |
158 | 256 | |
159 | 257 | if (nWrite < 0) { |
@@ -63,6 +63,9 @@ void TestInputMessageAlignment() { | ||
63 | 63 | CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 68); |
64 | 64 | CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 72); |
65 | 65 | CHECK_OFFSET(InputMessage::Body::Motion, pointers, 80); |
66 | + | |
67 | + CHECK_OFFSET(InputMessage::Body::Finished, seq, 0); | |
68 | + CHECK_OFFSET(InputMessage::Body::Finished, handled, 4); | |
66 | 69 | } |
67 | 70 | |
68 | 71 | } // namespace android |