@@ -156,7 +156,7 @@ enum {
156156
157157#ifdef BINDER_WITH_KERNEL_IPC
158158static void acquire_object (const sp<ProcessState>& proc, const flat_binder_object& obj,
159- const void * who) {
159+ const void * who, bool tagFds ) {
160160 switch (obj.hdr .type ) {
161161 case BINDER_TYPE_BINDER:
162162 if (obj.binder ) {
@@ -173,7 +173,7 @@ static void acquire_object(const sp<ProcessState>& proc, const flat_binder_objec
173173 return ;
174174 }
175175 case BINDER_TYPE_FD: {
176- if (obj.cookie != 0 ) { // owned
176+ if (tagFds && obj.cookie != 0 ) { // owned
177177 FdTag (obj.handle , nullptr , who);
178178 }
179179 return ;
@@ -611,7 +611,7 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
611611 }
612612 }
613613
614- acquire_object (proc, *flat, this );
614+ acquire_object (proc, *flat, this , true /* tagFds */ );
615615 }
616616 }
617617#else
@@ -1797,7 +1797,7 @@ status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
17971797 // Need to write meta-data?
17981798 if (nullMetaData || val.binder != 0 ) {
17991799 kernelFields->mObjects [kernelFields->mObjectsSize ] = mDataPos ;
1800- acquire_object (ProcessState::self (), val, this );
1800+ acquire_object (ProcessState::self (), val, this , true /* tagFds */ );
18011801 kernelFields->mObjectsSize ++;
18021802 }
18031803
@@ -2728,6 +2728,65 @@ size_t Parcel::ipcObjectsCount() const
27282728 return 0 ;
27292729}
27302730
2731+ static void do_nothing_release_func (const uint8_t * data, size_t dataSize,
2732+ const binder_size_t * objects, size_t objectsCount) {
2733+ (void )data;
2734+ (void )dataSize;
2735+ (void )objects;
2736+ (void )objectsCount;
2737+ }
2738+ static void delete_data_release_func (const uint8_t * data, size_t dataSize,
2739+ const binder_size_t * objects, size_t objectsCount) {
2740+ delete[] data;
2741+ (void )dataSize;
2742+ (void )objects;
2743+ (void )objectsCount;
2744+ }
2745+
2746+ void Parcel::makeDangerousViewOf (Parcel* p) {
2747+ if (p->isForRpc ()) {
2748+ // warning: this must match the logic in rpcSetDataReference
2749+ auto * rf = p->maybeRpcFields ();
2750+ LOG_ALWAYS_FATAL_IF (rf == nullptr );
2751+ std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>> fds;
2752+ if (rf->mFds ) {
2753+ fds.reserve (rf->mFds ->size ());
2754+ for (const auto & fd : *rf->mFds ) {
2755+ fds.push_back (binder::borrowed_fd (toRawFd (fd)));
2756+ }
2757+ }
2758+ status_t result =
2759+ rpcSetDataReference (rf->mSession , p->mData , p->mDataSize ,
2760+ rf->mObjectPositions .data (), rf->mObjectPositions .size (),
2761+ std::move (fds), do_nothing_release_func);
2762+ LOG_ALWAYS_FATAL_IF (result != OK, " Failed: %s" , statusToString (result).c_str ());
2763+ } else {
2764+ #ifdef BINDER_WITH_KERNEL_IPC
2765+ // warning: this must match the logic in ipcSetDataReference
2766+ auto * kf = p->maybeKernelFields ();
2767+ LOG_ALWAYS_FATAL_IF (kf == nullptr );
2768+
2769+ // Ownership of FDs is passed to the Parcel from kernel binder. This should be refactored
2770+ // to move this ownership out of Parcel and into release_func. However, today, Parcel
2771+ // always assums it can own and close FDs today. So, for purposes of testing consistency,
2772+ // , create new FDs it can own.
2773+
2774+ uint8_t * newData = new uint8_t [p->mDataSize ]; // deleted by delete_data_release_func
2775+ memcpy (newData, p->mData , p->mDataSize );
2776+ for (size_t i = 0 ; i < kf->mObjectsSize ; i++) {
2777+ flat_binder_object* flat =
2778+ reinterpret_cast <flat_binder_object*>(newData + kf->mObjects [i]);
2779+ if (flat->hdr .type == BINDER_TYPE_FD) {
2780+ flat->handle = fcntl (flat->handle , F_DUPFD_CLOEXEC, 0 );
2781+ }
2782+ }
2783+
2784+ ipcSetDataReference (newData, p->mDataSize , kf->mObjects , kf->mObjectsSize ,
2785+ delete_data_release_func);
2786+ #endif // BINDER_WITH_KERNEL_IPC
2787+ }
2788+ }
2789+
27312790void Parcel::ipcSetDataReference (const uint8_t * data, size_t dataSize, const binder_size_t * objects,
27322791 size_t objectsCount, release_func relFunc) {
27332792 // this code uses 'mOwner == nullptr' to understand whether it owns memory
@@ -2738,6 +2797,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const bin
27382797 auto * kernelFields = maybeKernelFields ();
27392798 LOG_ALWAYS_FATAL_IF (kernelFields == nullptr ); // guaranteed by freeData.
27402799
2800+ // must match makeDangerousViewOf
27412801 mData = const_cast <uint8_t *>(data);
27422802 mDataSize = mDataCapacity = dataSize;
27432803 kernelFields->mObjects = const_cast <binder_size_t *>(objects);
@@ -2816,6 +2876,7 @@ status_t Parcel::rpcSetDataReference(
28162876 auto * rpcFields = maybeRpcFields ();
28172877 LOG_ALWAYS_FATAL_IF (rpcFields == nullptr ); // guaranteed by markForRpc.
28182878
2879+ // must match makeDangerousViewOf
28192880 mData = const_cast <uint8_t *>(data);
28202881 mDataSize = mDataCapacity = dataSize;
28212882 mOwner = relFunc;
@@ -2883,15 +2944,17 @@ void Parcel::releaseObjects()
28832944#endif // BINDER_WITH_KERNEL_IPC
28842945}
28852946
2886- void Parcel::acquireObjects ()
2887- {
2947+ void Parcel::reacquireObjects (size_t objectsSize) {
28882948 auto * kernelFields = maybeKernelFields ();
28892949 if (kernelFields == nullptr ) {
28902950 return ;
28912951 }
28922952
28932953#ifdef BINDER_WITH_KERNEL_IPC
2894- size_t i = kernelFields->mObjectsSize ;
2954+ LOG_ALWAYS_FATAL_IF (objectsSize > kernelFields->mObjectsSize ,
2955+ " Object size %zu out of range of %zu" , objectsSize,
2956+ kernelFields->mObjectsSize );
2957+ size_t i = objectsSize;
28952958 if (i == 0 ) {
28962959 return ;
28972960 }
@@ -2901,8 +2964,10 @@ void Parcel::acquireObjects()
29012964 while (i > 0 ) {
29022965 i--;
29032966 const flat_binder_object* flat = reinterpret_cast <flat_binder_object*>(data + objects[i]);
2904- acquire_object (proc, *flat, this );
2967+ acquire_object (proc, *flat, this , false /* tagFds */ ); // they are already tagged
29052968 }
2969+ #else
2970+ (void ) objectsSize;
29062971#endif // BINDER_WITH_KERNEL_IPC
29072972}
29082973
@@ -3119,12 +3184,8 @@ status_t Parcel::continueWrite(size_t desired)
31193184 return NO_MEMORY;
31203185 }
31213186
3122- // Little hack to only acquire references on objects
3123- // we will be keeping.
3124- size_t oldObjectsSize = kernelFields->mObjectsSize ;
3125- kernelFields->mObjectsSize = objectsSize;
3126- acquireObjects ();
3127- kernelFields->mObjectsSize = oldObjectsSize;
3187+ // only acquire references on objects we are keeping
3188+ reacquireObjects (objectsSize);
31283189 }
31293190 if (rpcFields) {
31303191 if (status_t status = truncateRpcObjects (objectsSize); status != OK) {
0 commit comments