Fix binder memory handling for 64 bit devices

Change MemoryHeap offset to use off_t.
Always transmit Memory related size and offset as 64 bits.

Test: CTS, native binder tests, sanity
Bug: 117556990
Change-Id: Icaabf7442f561a53941f9ebebe4029ddc533b0c2
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 507ce53..0b89879 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -86,7 +86,7 @@
     virtual void* getBase() const;
     virtual size_t getSize() const;
     virtual uint32_t getFlags() const;
-    virtual uint32_t getOffset() const;
+    off_t getOffset() const override;
 
 private:
     friend class IMemory;
@@ -113,7 +113,7 @@
     mutable void*       mBase;
     mutable size_t      mSize;
     mutable uint32_t    mFlags;
-    mutable uint32_t    mOffset;
+    mutable off_t       mOffset;
     mutable bool        mRealHeap;
     mutable Mutex       mLock;
 };
@@ -187,13 +187,16 @@
         data.writeInterfaceToken(IMemory::getInterfaceDescriptor());
         if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {
             sp<IBinder> heap = reply.readStrongBinder();
-            ssize_t o = reply.readInt32();
-            size_t s = reply.readInt32();
             if (heap != nullptr) {
                 mHeap = interface_cast<IMemoryHeap>(heap);
                 if (mHeap != nullptr) {
+                    const int64_t offset64 = reply.readInt64();
+                    const uint64_t size64 = reply.readUint64();
+                    const ssize_t o = (ssize_t)offset64;
+                    const size_t s = (size_t)size64;
                     size_t heapSize = mHeap->getSize();
-                    if (s <= heapSize
+                    if (s == size64 && o == offset64 // ILP32 bounds check
+                            && s <= heapSize
                             && o >= 0
                             && (static_cast<size_t>(o) <= heapSize - s)) {
                         mOffset = o;
@@ -233,8 +236,8 @@
             ssize_t offset;
             size_t size;
             reply->writeStrongBinder( IInterface::asBinder(getMemory(&offset, &size)) );
-            reply->writeInt32(offset);
-            reply->writeInt32(size);
+            reply->writeInt64(offset);
+            reply->writeUint64(size);
             return NO_ERROR;
         } break;
         default:
@@ -313,18 +316,23 @@
         data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
         status_t err = remote()->transact(HEAP_ID, data, &reply);
         int parcel_fd = reply.readFileDescriptor();
-        ssize_t size = reply.readInt32();
-        uint32_t flags = reply.readInt32();
-        uint32_t offset = reply.readInt32();
-
-        ALOGE_IF(err, "binder=%p transaction failed fd=%d, size=%zd, err=%d (%s)",
-                IInterface::asBinder(this).get(),
-                parcel_fd, size, err, strerror(-err));
+        const uint64_t size64 = reply.readUint64();
+        const int64_t offset64 = reply.readInt64();
+        const uint32_t flags = reply.readUint32();
+        const size_t size = (size_t)size64;
+        const off_t offset = (off_t)offset64;
+        if (err != NO_ERROR || // failed transaction
+                size != size64 || offset != offset64) { // ILP32 size check
+            ALOGE("binder=%p transaction failed fd=%d, size=%zu, err=%d (%s)",
+                    IInterface::asBinder(this).get(),
+                    parcel_fd, size, err, strerror(-err));
+            return;
+        }
 
         Mutex::Autolock _l(mLock);
         if (mHeapId.load(memory_order_relaxed) == -1) {
             int fd = fcntl(parcel_fd, F_DUPFD_CLOEXEC, 0);
-            ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
+            ALOGE_IF(fd == -1, "cannot dup fd=%d, size=%zu, err=%d (%s)",
                     parcel_fd, size, err, strerror(errno));
 
             int access = PROT_READ;
@@ -334,7 +342,7 @@
             mRealHeap = true;
             mBase = mmap(nullptr, size, access, MAP_SHARED, fd, offset);
             if (mBase == MAP_FAILED) {
-                ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)",
+                ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zu, fd=%d (%s)",
                         IInterface::asBinder(this).get(), size, fd, strerror(errno));
                 close(fd);
             } else {
@@ -368,7 +376,7 @@
     return mFlags;
 }
 
-uint32_t BpMemoryHeap::getOffset() const {
+off_t BpMemoryHeap::getOffset() const {
     assertMapped();
     return mOffset;
 }
@@ -390,9 +398,9 @@
        case HEAP_ID: {
             CHECK_INTERFACE(IMemoryHeap, data, reply);
             reply->writeFileDescriptor(getHeapID());
-            reply->writeInt32(getSize());
-            reply->writeInt32(getFlags());
-            reply->writeInt32(getOffset());
+            reply->writeUint64(getSize());
+            reply->writeInt64(getOffset());
+            reply->writeUint32(getFlags());
             return NO_ERROR;
         } break;
         default: