blob: 7e9a04d91130e5e18be2e4923b618b1bde5bcc34 [file]
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <gtest/gtest.h>
#include "binder/Binder.h"
#include "binder/Parcel.h"
namespace android {
inline void readFdsTest(Parcel& p, int fd) {
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeDupFileDescriptor(fd));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeDupFileDescriptor(fd));
p.setDataPosition(0);
uint8_t data[sizeof(int32_t) * 2];
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t)));
EXPECT_NE(-1, p.readFileDescriptor());
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t) * 2));
EXPECT_NE(-1, p.readFileDescriptor());
}
// Reading over FDs with the wrong APIs is not allowed
inline void readOverFdsTest(Parcel& p, int fd, size_t sizeofFd) {
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeDupFileDescriptor(fd));
size_t dataPosBetweenFds = p.dataPosition();
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeDupFileDescriptor(fd));
p.setDataPosition(0);
#ifdef __TRUSTY__
// Trusty builds don't allow variable length arrays and don't have access
// to kernel binder so always use int32_t + size of RPC FD object
ASSERT_LE(sizeofFd, sizeof(int32_t) + sizeof(int32_t));
uint8_t data[sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t)];
#else
uint8_t data[sizeof(int32_t) + sizeofFd];
#endif // __TRUSTY__
EXPECT_EQ(PERMISSION_DENIED, p.read((void*)data, sizeof(int32_t) + sizeofFd));
p.setDataPosition(dataPosBetweenFds);
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t) * 2));
EXPECT_EQ(PERMISSION_DENIED, p.read((void*)data, sizeofFd));
}
// Using the read/writeBinder APIs is OK to read objects in parcels
inline void readBindersTest(Parcel& p, const sp<IBinder>& b) {
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeStrongBinder(b));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeStrongBinder(b));
p.setDataPosition(0);
uint8_t data[sizeof(int32_t) * 2];
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t)));
sp<IBinder> b2;
EXPECT_EQ(OK, p.readStrongBinder(&b2));
b2.clear();
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t) * 2));
EXPECT_EQ(OK, p.readStrongBinder(&b2));
}
// Reading over binder objects with the wrong APIs is not allowed
inline void readOverBindersTest(Parcel& p, const sp<IBinder>& b, size_t sizeofBinder) {
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeStrongBinder(b));
size_t dataPosBetweenBinders = p.dataPosition();
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeInt32(1));
EXPECT_EQ(OK, p.writeStrongBinder(b));
p.setDataPosition(0);
#ifdef __TRUSTY__
// Trusty builds don't allow variable length arrays and don't have access
// to kernel binder so always use int32_t + size of RPC binder object
ASSERT_LE(sizeofBinder, sizeof(int32_t) + sizeof(uint64_t));
uint8_t data[sizeof(int32_t) + sizeof(int32_t) + sizeof(uint64_t)];
#else
uint8_t data[sizeof(int32_t) + sizeofBinder];
#endif // __TRUSTY__
EXPECT_EQ(PERMISSION_DENIED, p.read((void*)data, sizeof(int32_t) + sizeofBinder));
p.setDataPosition(dataPosBetweenBinders);
EXPECT_EQ(OK, p.read((void*)data, sizeof(int32_t) * 2));
EXPECT_EQ(PERMISSION_DENIED, p.read((void*)data, sizeofBinder));
}
} // namespace android