!1247 fix IPC GetProtoInfo DOS bug.

Merge pull request !1247 from LDH/master
This commit is contained in:
openharmony_ci 2024-08-04 16:36:02 +00:00 committed by Gitee
commit ddf929b304
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
27 changed files with 993 additions and 136 deletions

View File

@ -22,6 +22,19 @@
#include "iremote_object.h"
namespace OHOS {
#ifndef CONFIG_IPC_SINGLE
struct DBinderNegotiationData {
pid_t peerPid;
pid_t peerUid;
uint32_t peerTokenId;
uint64_t stubIndex;
std::string peerServiceName;
std::string peerDeviceId;
std::string localServiceName;
std::string localDeviceId;
};
#endif
class IPCObjectProxy : public IRemoteObject {
public:
explicit IPCObjectProxy(int handle, std::u16string descriptor = std::u16string(),
@ -203,10 +216,11 @@ public:
/**
* @brief Wait for initialization.
* @param dbinderData dbinder object data.
* @return void
* @since 9
*/
void WaitForInit();
void WaitForInit(const void *dbinderData = nullptr);
/**
* @brief Obtains the interface descriptor.
@ -244,6 +258,14 @@ private:
*/
int UpdateProto();
/**
* @brief Update the proxy protocol.
* @param dbinderData Indicates a dbinder object data.
* @return Returns <b>true</b> if the operation is successful; return <b>false</b> otherwise.
* @since 12
*/
bool UpdateProto(const void *dbinderData);
/**
* @brief Release the proxy protocol.
* @return void
@ -297,19 +319,32 @@ private:
/**
* @brief Update the databus(Dbinder) client session name.
* @param hadle Indicates a hadel that needs to update session information.
* @param handle Indicates a handle that needs to update session information.
* @param reply Indicates the object returned by the peer process.
* @return Returns <b>true</b> if the update is successful; returns <b>false</b> Otherwise.
* @since 9
*/
bool UpdateDatabusClientSession(int handle, MessageParcel &reply);
/**
* @brief Update the databus(Dbinder) client session name.
* @return Returns <b>true</b> if the update is successful; returns <b>false</b> Otherwise.
* @since 12
*/
bool UpdateDatabusClientSession();
/**
* @brief Check if there is a session.
* @return Returns <b>true</b> if there is currently a session; returns <b>false</b> otherwise.
* @since 9
*/
bool CheckHaveSession();
int GetDBinderNegotiationData(int handle, MessageParcel &reply, DBinderNegotiationData &dbinderData);
int GetDBinderNegotiationData(DBinderNegotiationData &dbinderData);
bool MakeDBinderTransSession(const DBinderNegotiationData &data);
#endif
private:
@ -325,6 +360,7 @@ private:
std::u16string interfaceDesc_;
int lastErr_ = 0;
int lastErrCnt_ = 0;
std::unique_ptr<uint8_t[]> dbinderData_{nullptr};
};
} // namespace OHOS
#endif // OHOS_IPC_IPC_OBJECT_PROXY_H

View File

@ -218,6 +218,17 @@ public:
* @since 12
*/
void SetRequestSidFlag(bool flag);
/**
* @brief Get and save the dbinder object data.
* @param pid Indicates the sender pid.
* @param uid Indicates the sender uid.
* @return Returns {@link ERR_NONE} if the operation is successful; returns an error code
* defined in {@link ipc_types.h} otherwise.
* @since 12
*/
virtual int GetAndSaveDBinderData(pid_t pid, uid_t uid);
#ifndef CONFIG_IPC_SINGLE
/**
* @brief Invoker the calling thread.
@ -262,8 +273,10 @@ public:
* @since 9
*/
int32_t AddAuthInfo(MessageParcel &data, MessageParcel &reply, uint32_t code);
#endif
private:
#ifndef CONFIG_IPC_SINGLE
std::string GetSessionName();
int GetSessionNameForPidUid(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
int GetGrantedSessionName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
@ -277,7 +290,7 @@ private:
int DBinderGetSessionName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
int DBinderGetPidUid(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
#endif
private:
bool IsDeviceIdIllegal(const std::string &deviceID);
int DBinderPingTransaction(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
int DBinderInterfaceTransaction(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
@ -286,7 +299,6 @@ private:
int SendRequestInner(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option);
void InitCodeMap();
private:
std::recursive_mutex serialRecursiveMutex_;
bool serialInvokeFlag_;
uint64_t lastRequestTime_;

View File

@ -123,6 +123,7 @@ enum {
IPC_INVOKER_ON_TRANSACT_ERR,
IPC_INVOKER_INVALID_DATA_ERR,
IPC_INVOKER_INVALID_REPLY_ERR,
IPC_TRANSLATE_DBINDER_STUB_ERR,
RPC_BASE_INVOKER_ERR = 500,
RPC_BASE_INVOKER_INVALID_REPLY_ERR,
RPC_BASE_INVOKER_WAIT_REPLY_ERR,
@ -142,6 +143,9 @@ enum {
DBINDER_SERVICE_ADD_DEATH_ERR,
DBINDER_SERVICE_REMOVE_DEATH_ERR,
DBINDER_SERVICE_WRONG_SESSION,
DBINDER_SERVICE_FILL_DATA_ERR,
DBINDER_SERVICE_MEMCPY_ERR,
DBINDER_SERVICE_MALLOC_ERR,
SESSION_WRONG_FD_ERR = 800,
SESSION_INVOKER_NULL_ERR,
SESSION_UNAUTHENTICATED_ERR,
@ -150,6 +154,9 @@ enum {
DBINDER_CALLBACK_ADD_DEATH_ERR,
DBINDER_CALLBACK_RMV_DEATH_ERR,
DBINDER_CALLBACK_READ_OBJECT_ERR,
DBINDER_CALLBACK_FILL_DATA_ERR,
DBINDER_CALLBACK_MEMCPY_ERR,
DBINDER_CALLBACK_MALLOC_ERR,
BINDER_CALLBACK_AUTHCOMM_ERR,
BINDER_CALLBACK_STUBINDEX_ERR
};

View File

@ -182,19 +182,36 @@ public:
*/
bool Append(MessageParcel &data);
/**
* @brief Print the content in MessgaeParcel buffer.
* @param funcName Indicates the invoke function name.
* @param lineNum Indicates the invoke function line number.
* @return void
* @since 12
*/
void PrintBuffer(const char *funcName, const size_t lineNum);
private:
#ifndef CONFIG_IPC_SINGLE
/**
* @brief Write to the DBinder proxy object.
* @param object Indicates an IRemoteObject type object.
* @param handle Indicates the handle to write.
* @param stubIndex Indicates the stub index to write to.
* @return Returns <b>true</b> if the write succeeds; returns <b>false</b> otherwise.
* @since
* @since 9
*/
bool WriteDBinderProxy(const sptr<IRemoteObject> &object, uint32_t handle, uint64_t stubIndex);
/**
* @brief Update the DBinder object's offset.
* @param offset Indicates the object offset.
* @return Returns <b>true</b> if the update succeeds; returns <b>false</b> otherwise.
* @since 12
*/
bool UpdateDBinderDataOffset(size_t offset);
#endif
static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M
static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k
bool needCloseFd_ = false;

View File

@ -73,6 +73,8 @@
"OHOS::IRemoteObject::GetInterfaceDescriptor()";
"OHOS::IPCObjectProxy::GetInterfaceDescriptor()";
"OHOS::IPCObjectStub::GetInterfaceDescriptor()";
"OHOS::IPCObjectStub::GetAndSaveDBinderData(int, unsigned int)";
"virtual thunk to OHOS::IPCObjectStub::GetAndSaveDBinderData(int, unsigned int)";
};
local:
*;

View File

@ -72,7 +72,10 @@ ohos_shared_library("ipc_single") {
"hitrace:libhitracechain",
"selinux:libselinux",
]
defines = [ "FFRT_IPC_ENABLE" ]
defines = [
"CONFIG_IPC_SINGLE",
"FFRT_IPC_ENABLE",
]
if (build_selinux) {
defines += [ "WITH_SELINUX" ]
}

View File

@ -96,6 +96,8 @@
"OHOS::IRemoteObject::GetInterfaceDescriptor()";
"OHOS::IPCObjectProxy::GetInterfaceDescriptor()";
"OHOS::IPCObjectStub::GetInterfaceDescriptor()";
"OHOS::IPCObjectStub::GetAndSaveDBinderData(int, unsigned int)";
"virtual thunk to OHOS::IPCObjectStub::GetAndSaveDBinderData(int, unsigned int)";
"OHOS::IPC_SINGLE::InvokerFactory::Get()";
"OHOS::IPC_SINGLE::InvokerFactory::Register(int, std::__h::function<OHOS::IPC_SINGLE::IRemoteInvoker* ()>)";
};

View File

@ -14,6 +14,7 @@
import("//build/ohos.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native"
DBINDER_ROOT = "$SUBSYSTEM_DIR/services/dbinder"
config("libdbinder_config") {
@ -59,7 +60,11 @@ ohos_shared_library("libdbinder") {
]
configs = [ ":libdbinder_private_config" ]
deps = [ "$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core:ipc_core" ]
deps = [
"$IPC_CORE_ROOT/src/core:ipc_common",
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core:ipc_core",
]
external_deps = [
"c_utils:utils",
"ffrt:libffrt",

View File

@ -33,6 +33,23 @@ public:
binder_uintptr_t binderObject);
~DBinderServiceStub();
/**
* @brief Serialize a specified DBinderServiceStub object.
* @param parcel Indicates the object storing the data.
* @param object Indicates the serialized object.
* @return Returns <b>true</b> if serialized successfully; returns <b>false</b> otherwise.
* @since 12
*/
static bool Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object);
/**
* @brief Serialize self.
* @param parcel Indicates the object storing the data.
* @return Returns <b>true</b> if serialized successfully; returns <b>false</b> otherwise.
* @since 12
*/
bool Marshalling(Parcel &parcel) const override;
/**
* @brief Gets the process protocol.
* @param code Indicates the message code of the request.
@ -55,6 +72,16 @@ public:
*/
int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
/**
* @brief Get and save the dbinder object data.
* @param pid Indicates the sender pid.
* @param uid Indicates the sender uid.
* @return Returns {@link ERR_NONE} if the operation is successful; returns an error code
* defined in {@link ipc_types.h} otherwise.
* @since 12
*/
int GetAndSaveDBinderData(pid_t pid, uid_t uid) override;
/**
* @brief Obtains the service name.
* @return Returns the service name.
@ -77,12 +104,16 @@ public:
binder_uintptr_t GetBinderObject() const;
private:
const std::string serviceName_;
const std::string deviceID_;
binder_uintptr_t binderObject_;
int32_t ProcessDeathRecipient(MessageParcel &data, MessageParcel &reply);
int32_t AddDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply);
int32_t RemoveDbinderDeathRecipient(MessageParcel &data, MessageParcel &reply);
bool CheckSessionObjectValidity();
int SaveDBinderData(const std::string &localBusName);
const std::string serviceName_;
const std::string deviceID_;
binder_uintptr_t binderObject_;
std::unique_ptr<uint8_t[]> dbinderData_ {nullptr};
};
} // namespace OHOS
#endif // OHOS_IPC_SERVICES_DBINDER_DBINDER_STUB_H

View File

@ -25,6 +25,9 @@ public:
explicit DBinderCallbackStub(const std::string &serviceName, const std::string &peerDeviceID,
const std::string &localDeviceID, uint64_t stubIndex, uint32_t handle, uint32_t tokenId);
~DBinderCallbackStub();
static bool Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object);
bool Marshalling(Parcel &parcel) const override;
int GetAndSaveDBinderData(pid_t pid, uid_t uid) override;
int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
@ -35,12 +38,15 @@ public:
private:
int32_t ProcessData(int uid, int pid, const std::string &sessionName, MessageParcel &data, MessageParcel &reply);
int AddDBinderCommAuth(pid_t pid, uid_t uid, const std::string &sessionName);
int SaveDBinderData(const std::string &sessionName);
const std::string serviceName_;
const std::string deviceID_;
const std::string localDeviceID_;
uint64_t stubIndex_;
uint32_t handle_;
uint32_t tokenId_;
std::unique_ptr<uint8_t[]> dbinderData_ {nullptr};
};
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_CALLBACK_STUB_H

View File

@ -90,7 +90,7 @@ public:
bool OnThreadTerminated(const std::string &threadName);
bool SpawnThread(int policy = IPCWorkThread::SPAWN_PASSIVE, int proto = IRemoteObject::IF_PROT_DEFAULT);
sptr<IRemoteObject> FindOrNewObject(int handle);
sptr<IRemoteObject> FindOrNewObject(int handle, const dbinder_negotiation_data *dbinderData = nullptr);
bool IsContainsObject(IRemoteObject *object);
sptr<IRemoteObject> QueryObject(const std::u16string &descriptor, bool lockFlag = true);
bool AttachObject(IRemoteObject *object, bool lockFlag = true);

View File

@ -21,6 +21,7 @@
#include <shared_mutex>
#include "iremote_object.h"
#include "sys_binder.h"
namespace OHOS {
struct DeadObjectInfo {
@ -43,10 +44,13 @@ struct InvokerProcInfo {
class ProcessSkeleton {
public:
static std::string ConvertToSecureDesc(const std::string &str);
bool SetIPCProxyLimit(uint64_t num, std::function<void (uint64_t num)> callback);
static bool IsPrint(int err, int &lastErr, int &lastErrCnt);
static uint32_t ConvertAddr(const void *ptr);
static ProcessSkeleton* GetInstance();
static bool FlattenDBinderData(Parcel &parcel, const dbinder_negotiation_data *&dbinderData);
static bool UnFlattenDBinderData(Parcel &parcel, dbinder_negotiation_data *&dbinderData);
bool SetIPCProxyLimit(uint64_t num, std::function<void (uint64_t num)> callback);
sptr<IRemoteObject> GetRegistryObject();
void SetRegistryObject(sptr<IRemoteObject> &object);
void SetSamgrFlag(bool flag);

View File

@ -24,6 +24,7 @@
#include "ipc_skeleton.h"
#include "ipc_thread_skeleton.h"
#include "ipc_types.h"
#include "securec.h"
#include "string_ex.h"
#include "sys_binder.h"
@ -43,6 +44,10 @@ DBinderCallbackStub::DBinderCallbackStub(const std::string &service, const std::
{
ZLOGD(LOG_LABEL, "created, service:%{public}s deviceId:%{public}s handle:%{public}u stubIndex:%{public}" PRIu64,
serviceName_.c_str(), IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(), handle_, stubIndex_);
dbinderData_ = std::make_unique<uint8_t[]>(sizeof(dbinder_negotiation_data));
if (dbinderData_ == nullptr) {
ZLOGE(LOG_LABEL, "malloc dbinderData_ fail");
}
}
DBinderCallbackStub::~DBinderCallbackStub()
@ -50,6 +55,7 @@ DBinderCallbackStub::~DBinderCallbackStub()
ZLOGD(LOG_LABEL, "destroyed, service:%{public}s deviceId:%{public}s handle:%{public}u stubIndex:%{public}" PRIu64,
serviceName_.c_str(), IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(), handle_, stubIndex_);
IPCProcessSkeleton::GetCurrent()->DetachDBinderCallbackStub(this);
dbinderData_ = nullptr;
}
const std::string &DBinderCallbackStub::GetServiceName()
@ -157,4 +163,142 @@ int32_t DBinderCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
return result;
}
bool DBinderCallbackStub::Marshalling(Parcel &parcel) const
{
ZLOGD(LOG_LABEL, "enter");
if (dbinderData_ == nullptr) {
ZLOGE(LOG_LABEL, "dbinderData_ is nullptr");
return false;
}
auto *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker == nullptr) {
ZLOGE(LOG_LABEL, "GetRemoteInvoker fail");
return false;
}
size_t offset = parcel.GetWritePosition();
auto dbinderData = reinterpret_cast<const dbinder_negotiation_data *>(dbinderData_.get());
if (!ProcessSkeleton::FlattenDBinderData(parcel, dbinderData)) {
return false;
}
if (!invoker->FlattenObject(parcel, this)) {
ZLOGE(LOG_LABEL, "FlattenObject fail");
parcel.RewindWrite(offset);
return false;
}
return true;
}
bool DBinderCallbackStub::Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object)
{
ZLOGD(LOG_LABEL, "enter");
auto callback = reinterpret_cast<DBinderCallbackStub *>(object.GetRefPtr());
if (callback == nullptr) {
return false;
}
return callback->Marshalling(parcel);
}
int DBinderCallbackStub::AddDBinderCommAuth(pid_t pid, uid_t uid, const std::string &sessionName)
{
MessageParcel authData, authReply;
MessageOption authOption;
if (!authData.WriteUint32(pid) || !authData.WriteUint32(uid) || !authData.WriteString(localDeviceID_) ||
!authData.WriteUint64(stubIndex_) || !authData.WriteUint32(tokenId_)) {
ZLOGE(LOG_LABEL, "write to MessageParcel fail");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_WRITE_TO_PARCEL_FAIL, __FUNCTION__);
return IPC_STUB_WRITE_PARCEL_ERR;
}
IRemoteInvoker *dbinderInvoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS);
if (dbinderInvoker == nullptr) {
ZLOGE(LOG_LABEL, "no databus thread and invoker");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_RPC_DATABUS_INVOKER_ERR, __FUNCTION__);
return RPC_DATABUS_INVOKER_ERR;
}
int err = dbinderInvoker->SendRequest(handle_, DBINDER_ADD_COMMAUTH, authData, authReply, authOption);
if (err != ERR_NONE) {
ZLOGE(LOG_LABEL, "send auth info to remote fail");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_BINDER_CALLBACK_AUTHCOMM_ERR, __FUNCTION__);
return BINDER_CALLBACK_AUTHCOMM_ERR;
}
ZLOGI(LOG_LABEL, "send to stub ok! stubIndex:%{public}" PRIu64 " peerDevice:%{public}s "
"localDeviceID:%{public}s serviceName:%{public}s uid:%{public}d pid:%{public}d "
"tokenId:%{public}u sessionName:%{public}s",
stubIndex_, IPCProcessSkeleton::ConvertToSecureString(deviceID_).c_str(),
IPCProcessSkeleton::ConvertToSecureString(localDeviceID_).c_str(), serviceName_.c_str(), uid, pid, tokenId_,
sessionName.c_str());
return ERR_NONE;
}
int DBinderCallbackStub::SaveDBinderData(const std::string &sessionName)
{
if (dbinderData_ == nullptr) {
ZLOGE(LOG_LABEL, "dbinderData_ is nullptr");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
return DBINDER_CALLBACK_MALLOC_ERR;
}
dbinder_negotiation_data *dbinderData = reinterpret_cast<dbinder_negotiation_data *>(dbinderData_.get());
dbinderData->proto = IRemoteObject::IF_PROT_DATABUS;
dbinderData->stub_index = stubIndex_;
dbinderData->tokenid = tokenId_;
auto ret = memcpy_s(dbinderData->target_name, SESSION_NAME_LENGTH, serviceName_.c_str(),
serviceName_.length());
ret += memcpy_s(dbinderData->target_device, DEVICEID_LENGTH, deviceID_.c_str(),
deviceID_.length());
ret += memcpy_s(dbinderData->local_device, DEVICEID_LENGTH, localDeviceID_.c_str(),
localDeviceID_.length());
ret += memcpy_s(dbinderData->local_name, SESSION_NAME_LENGTH, sessionName.c_str(), sessionName.length());
ret += memcpy_s(dbinderData->desc, DBINDER_DESC_LENGTH, descriptor_.c_str(), descriptor_.length());
if (ret != EOK) {
ZLOGE(LOG_LABEL, "memcpy_s fail, ret:%{public}d", ret);
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
return DBINDER_CALLBACK_MEMCPY_ERR;
}
ZLOGI(LOG_LABEL, "proto:%{public}u stubIndex:%{public}llu tokenId:%{public}u "
"targetName:%{public}s localName:%{public}s",
dbinderData->proto, dbinderData->stub_index, dbinderData->tokenid, dbinderData->target_name,
dbinderData->local_name);
return ERR_NONE;
}
int DBinderCallbackStub::GetAndSaveDBinderData(pid_t pid, uid_t uid)
{
if (uid < 0 || pid < 0) {
ZLOGE(LOG_LABEL, "uid(%{public}d) or pid(%{public}d) is invalid", uid, pid);
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_UID_OR_PID_FAIL, __FUNCTION__);
return DBINDER_CALLBACK_FILL_DATA_ERR;
}
sptr<IRemoteObject> object = IPCProcessSkeleton::GetCurrent()->GetSAMgrObject();
if (object == nullptr) {
ZLOGE(LOG_LABEL, "GetSAMgrObject failed");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SA_OBJECT_NULL, __FUNCTION__);
return DBINDER_CALLBACK_FILL_DATA_ERR;
}
IPCObjectProxy *samgr = reinterpret_cast<IPCObjectProxy *>(object.GetRefPtr());
std::string sessionName = samgr->GetSessionNameForPidUid(uid, pid);
if (sessionName.empty()) {
ZLOGE(LOG_LABEL, "GetSessionNameForPidUid failed");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SESSION_NAME_FAIL, __FUNCTION__);
return DBINDER_CALLBACK_FILL_DATA_ERR;
}
int ret = AddDBinderCommAuth(pid, uid, sessionName);
if (ret != ERR_NONE) {
ZLOGE(LOG_LABEL, "AddDBinderCommAuth failed");
return ret;
}
ret = SaveDBinderData(sessionName);
if (ret != ERR_NONE) {
ZLOGE(LOG_LABEL, "SaveDBinderData failed");
return ret;
}
return ERR_NONE;
}
} // namespace OHOS

View File

@ -97,7 +97,9 @@ uint64_t DBinderSessionObject::GetStubIndex() const
uint32_t DBinderSessionObject::GetFlatSessionLen()
{
return sizeof(struct FlatDBinderSession);
auto length = sizeof(struct FlatDBinderSession);
ZLOGD(LOG_LABEL, "FlatDBinderSession size:%{public}zu", length);
return length;
}
int32_t DBinderSessionObject::GetSocketId() const

View File

@ -303,7 +303,7 @@ void IPCObjectProxy::OnFirstStrongRef(const void *objectId)
}
}
void IPCObjectProxy::WaitForInit()
void IPCObjectProxy::WaitForInit(const void *dbinderData)
{
// RPC proxy: AcquireHandle->AttachObject->Open Session->IncRef to Remote Stub
{
@ -320,8 +320,8 @@ void IPCObjectProxy::WaitForInit()
if (!isFinishInit_) {
#ifndef CONFIG_IPC_SINGLE
if (UpdateProto() == IRemoteObject::IF_PROT_ERROR) {
isRemoteDead_ = true;
if (!UpdateProto(dbinderData)) {
return;
}
#endif
isFinishInit_ = true;
@ -563,6 +563,16 @@ int IPCObjectProxy::InvokeListenThread(MessageParcel &data, MessageParcel &reply
return SendRequestInner(false, INVOKE_LISTEN_THREAD, data, reply, option);
}
uint32_t IPCObjectProxy::GetStrongRefCountForStub()
{
BinderInvoker *invoker = reinterpret_cast<BinderInvoker *>(IPCThreadSkeleton::GetDefaultInvoker());
if (invoker == nullptr) {
ZLOGE(LABEL, "get default invoker failed");
return 0; // 0 means get failed
}
return invoker->GetStrongRefCountForStub(handle_);
}
#ifndef CONFIG_IPC_SINGLE
int IPCObjectProxy::UpdateProto()
{
@ -571,6 +581,34 @@ int IPCObjectProxy::UpdateProto()
return proto;
}
bool IPCObjectProxy::UpdateProto(const void *dbinderData)
{
auto data = reinterpret_cast<const dbinder_negotiation_data *>(dbinderData);
if (data != nullptr && data->proto == IRemoteObject::IF_PROT_DATABUS) {
dbinderData_ = std::make_unique<uint8_t[]>(sizeof(dbinder_negotiation_data));
if (dbinderData_ == nullptr) {
isRemoteDead_ = true;
SetProto(IRemoteObject::IF_PROT_ERROR);
ZLOGE(LABEL, "malloc dbinderData fail, handle:%{public}d", handle_);
return false;
}
auto tmp = reinterpret_cast<dbinder_negotiation_data *>(dbinderData_.get());
*tmp = *data;
if (!UpdateDatabusClientSession()) {
ZLOGE(LABEL, "UpdateDatabusClientSession fail, handle:%{public}d", handle_);
isRemoteDead_ = true;
SetProto(IRemoteObject::IF_PROT_ERROR);
dbinderData_ = nullptr;
return false;
}
SetProto(IRemoteObject::IF_PROT_DATABUS);
remoteDescriptor_ = data->desc;
} else if (CheckHaveSession()) {
SetProto(IRemoteObject::IF_PROT_DATABUS);
}
return true;
}
int32_t IPCObjectProxy::IncRefToRemote()
{
MessageParcel data, reply;
@ -745,7 +783,7 @@ bool IPCObjectProxy::CheckHaveSession()
return current->ProxyMoveDBinderSession(handle_, this);
}
bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply)
bool IPCObjectProxy::MakeDBinderTransSession(const DBinderNegotiationData &data)
{
DBinderDatabusInvoker *invoker =
reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
@ -753,64 +791,118 @@ bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply
ZLOGE(LABEL, "invoker is null");
return false;
}
uint64_t stubIndex = reply.ReadUint64();
std::string serviceName = reply.ReadString();
std::string peerID = reply.ReadString();
std::string localID = reply.ReadString();
std::string localBusName = reply.ReadString();
uint32_t peerTokenId = reply.ReadUint32();
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current == nullptr) {
ZLOGE(LABEL, "skeleton is nullptr");
return false;
}
if (serviceName.empty()) {
if (data.peerServiceName.empty()) {
ZLOGE(LABEL, "serviceName is empty");
return false;
}
std::string str = serviceName.substr(DBINDER_SOCKET_NAME_PREFIX.length());
std::string::size_type pos = str.find("_");
std::string peerUid = str.substr(0, pos);
std::string peerPid = str.substr(pos + 1);
if (peerUid.empty() || peerPid.empty()) {
ZLOGE(LABEL, "peerUid or peerPid is empty");
return false;
}
std::shared_ptr<DBinderSessionObject> dbinderSession = std::make_shared<DBinderSessionObject>(
serviceName, peerID, stubIndex, this, peerTokenId);
auto dbinderSession = std::make_shared<DBinderSessionObject>(
data.peerServiceName, data.peerDeviceId, data.stubIndex, this, data.peerTokenId);
if (dbinderSession == nullptr) {
ZLOGE(LABEL, "make DBinderSessionObject fail!");
return false;
}
dbinderSession->SetPeerPid(std::stoi(peerPid));
dbinderSession->SetPeerUid(std::stoi(peerUid));
if (!current->CreateSoftbusServer(localBusName)) {
ZLOGE(LABEL, "create softbus server fail, name:%{public}s localID:%{public}s", localBusName.c_str(),
IPCProcessSkeleton::ConvertToSecureString(localID).c_str());
dbinderSession->SetPeerPid(data.peerPid);
dbinderSession->SetPeerUid(data.peerUid);
if (!current->CreateSoftbusServer(data.localServiceName)) {
ZLOGE(LABEL, "CreateSoftbusServer fail, name:%{public}s localID:%{public}s", data.localServiceName.c_str(),
IPCProcessSkeleton::ConvertToSecureString(data.localDeviceId).c_str());
return false;
}
if (!invoker->UpdateClientSession(dbinderSession)) {
// no need to remove softbus server
ZLOGE(LABEL, "update server session object fail!");
ZLOGE(LABEL, "UpdateClientSession fail!");
return false;
}
if (!current->ProxyAttachDBinderSession(handle, dbinderSession)) {
if (!current->ProxyAttachDBinderSession(handle_, dbinderSession)) {
// should not get here
ZLOGW(LABEL, "fail to attach session for handle:%{public}d, maybe a concurrent scenarios", handle);
if (current->QuerySessionByInfo(serviceName, peerID) == nullptr) {
ZLOGW(LABEL, "ProxyAttachDBinderSession fail for handle:%{public}d, maybe a concurrent scenarios", handle_);
if (current->QuerySessionByInfo(data.peerServiceName, data.peerDeviceId) == nullptr) {
ZLOGE(LABEL, "session is not exist, service:%{public}s devId:%{public}s",
serviceName.c_str(), IPCProcessSkeleton::ConvertToSecureString(peerID).c_str());
data.peerServiceName.c_str(), IPCProcessSkeleton::ConvertToSecureString(data.peerDeviceId).c_str());
dbinderSession->CloseDatabusSession();
return false;
}
}
ZLOGI(LABEL, "succ");
return true;
}
int IPCObjectProxy::GetDBinderNegotiationData(int handle, MessageParcel &reply,
DBinderNegotiationData &dbinderData)
{
dbinderData.stubIndex = reply.ReadUint64();
dbinderData.peerServiceName = reply.ReadString();
dbinderData.peerDeviceId = reply.ReadString();
dbinderData.localDeviceId = reply.ReadString();
dbinderData.localServiceName = reply.ReadString();
dbinderData.peerTokenId = reply.ReadUint32();
if (dbinderData.peerServiceName.empty() || dbinderData.peerDeviceId.empty() ||
dbinderData.localDeviceId.empty() || dbinderData.localServiceName.empty()) {
ZLOGE(LABEL, "invalid param");
return ERR_INVALID_DATA;
}
std::string str = dbinderData.peerServiceName.substr(DBINDER_SOCKET_NAME_PREFIX.length());
std::string::size_type pos = str.find("_");
if (pos == str.npos) {
ZLOGE(LABEL, "ServiceName format error");
return ERR_INVALID_DATA;
}
dbinderData.peerUid = std::stoi(str.substr(0, pos));
dbinderData.peerPid = std::stoi(str.substr(pos + 1));
return ERR_NONE;
}
bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply)
{
DBinderNegotiationData dbinderData;
if (GetDBinderNegotiationData(handle, reply, dbinderData) != ERR_NONE) {
return false;
}
return MakeDBinderTransSession(dbinderData);
}
int IPCObjectProxy::GetDBinderNegotiationData(DBinderNegotiationData &dbinderData)
{
if (dbinderData_ == nullptr) {
ZLOGE(LABEL, "dbinderData_ is null");
return ERR_INVALID_DATA;
}
auto data = reinterpret_cast<const dbinder_negotiation_data *>(dbinderData_.get());
dbinderData.stubIndex = data->stub_index;
dbinderData.peerServiceName = data->target_name;
dbinderData.peerDeviceId = data->target_device;
dbinderData.localDeviceId = data->local_device;
dbinderData.localServiceName = data->local_name;
dbinderData.peerTokenId = data->tokenid;
std::string str = dbinderData.peerServiceName.substr(DBINDER_SOCKET_NAME_PREFIX.length());
std::string::size_type pos = str.find("_");
if (pos == str.npos) {
ZLOGW(LABEL, "ServiceName format error");
return ERR_INVALID_DATA;
}
dbinderData.peerUid = std::stoi(str.substr(0, pos));
dbinderData.peerPid = std::stoi(str.substr(pos + 1));
return ERR_NONE;
}
bool IPCObjectProxy::UpdateDatabusClientSession()
{
DBinderNegotiationData dbinderData;
if (GetDBinderNegotiationData(dbinderData) != ERR_NONE) {
return false;
}
return MakeDBinderTransSession(dbinderData);
}
void IPCObjectProxy::ReleaseDatabusProto()
{
if (handle_ == 0) {
@ -845,15 +937,5 @@ void IPCObjectProxy::ReleaseBinderProto()
{
// do nothing
}
uint32_t IPCObjectProxy::GetStrongRefCountForStub()
{
BinderInvoker *invoker = reinterpret_cast<BinderInvoker *>(IPCThreadSkeleton::GetDefaultInvoker());
if (invoker == nullptr) {
ZLOGE(LABEL, "get default invoker failed");
return 0; // 0 means get failed
}
return invoker->GetStrongRefCountForStub(handle_);
}
#endif
} // namespace OHOS

View File

@ -729,4 +729,12 @@ void IPCObjectStub::SetRequestSidFlag(bool flag)
requestSidFlag_ = flag;
#endif
}
int IPCObjectStub::GetAndSaveDBinderData(pid_t pid, uid_t uid)
{
(void)pid;
(void)uid;
ZLOGW(LABEL, "unexpected call");
return ERR_INVALID_STATE;
}
} // namespace OHOS

View File

@ -187,7 +187,7 @@ std::u16string IPCProcessSkeleton::MakeHandleDescriptor(int handle)
return Str8ToStr16(descriptor);
}
sptr<IRemoteObject> IPCProcessSkeleton::FindOrNewObject(int handle)
sptr<IRemoteObject> IPCProcessSkeleton::FindOrNewObject(int handle, const dbinder_negotiation_data *dbinderData)
{
CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, nullptr);
bool newFlag = false;
@ -201,7 +201,7 @@ sptr<IRemoteObject> IPCProcessSkeleton::FindOrNewObject(int handle)
return result;
}
sptr<IPCObjectProxy> proxy = reinterpret_cast<IPCObjectProxy *>(result.GetRefPtr());
proxy->WaitForInit();
proxy->WaitForInit(dbinderData);
#ifndef CONFIG_IPC_SINGLE
if (proxy->GetProto() == IRemoteObject::IF_PROT_ERROR) {
uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(

View File

@ -34,6 +34,7 @@
#include "memory"
#include "new"
#include "parcel.h"
#include "process_skeleton.h"
#include "refbase.h"
#include "securec.h"
#include "sys_binder.h"
@ -119,7 +120,6 @@ MessageParcel::~MessageParcel()
}
ClearFileDescriptor();
rawData_ = nullptr;
rawDataSize_ = 0;
}
@ -160,6 +160,25 @@ bool MessageParcel::WriteDBinderProxy(const sptr<IRemoteObject> &object, uint32_
}
return WriteRemoteObject(fakeStub);
}
bool MessageParcel::UpdateDBinderDataOffset(size_t offset)
{
size_t curOffset = GetWritePosition();
const binder_buffer_object *obj = reinterpret_cast<const binder_buffer_object *>(GetData() + offset);
if (obj->hdr.type == BINDER_TYPE_PTR) {
if (obj->length == sizeof(dbinder_negotiation_data)) {
// update dbinder object offset
size_t objOffset = offset + sizeof(binder_buffer_object);
if (!WriteObjectOffset(objOffset)) {
RewindWrite(curOffset);
ZLOGE(LOG_LABEL, "update obj offset:%{public}zu fail, ptr offset:%{public}zu", objOffset, offset);
return false;
}
ZLOGI(LOG_LABEL, "update obj offset:%{public}zu, ptr offset:%{public}zu", objOffset, offset);
}
}
return true;
}
#endif
bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject> &object)
@ -181,11 +200,20 @@ bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject> &object)
}
}
#endif
auto result = WriteObject<IRemoteObject>(object);
if (result == false) {
return result;
#ifndef CONFIG_IPC_SINGLE
auto offset = GetWritePosition();
#endif
if (!WriteObject<IRemoteObject>(object)) {
return false;
}
return result;
#ifndef CONFIG_IPC_SINGLE
if (!UpdateDBinderDataOffset(offset)) {
RewindWrite(offset);
return false;
}
#endif
return true;
}
sptr<IRemoteObject> MessageParcel::ReadRemoteObject()
@ -230,13 +258,14 @@ int MessageParcel::ReadFileDescriptor()
sptr<IPCFileDescriptor> descriptor = ReadObject<IPCFileDescriptor>();
if (descriptor == nullptr) {
ZLOGE(LOG_LABEL, "ReadObject failed");
return -1;
return INVALID_FD;
}
int fd = descriptor->GetFd();
if (fd < 0) {
ZLOGE(LOG_LABEL, "get fd failed, invalid fd:%{public}d", fd);
return -1;
return INVALID_FD;
}
int dupFd = dup(fd);
if (dupFd < 0) {
ZLOGE(LOG_LABEL, "dup failed, fd:%{public}d, errno:%{public}d", fd, errno);
@ -386,6 +415,7 @@ bool MessageParcel::RestoreRawData(std::shared_ptr<char> rawData, size_t size)
if (rawData_ != nullptr || rawData == nullptr) {
return false;
}
ZLOGD(LOG_LABEL, "enter");
rawData_ = rawData;
rawDataSize_ = size;
writeRawDataFd_ = 0;
@ -552,4 +582,35 @@ bool MessageParcel::Append(MessageParcel &data)
}
return true;
}
void MessageParcel::PrintBuffer(const char *funcName, const size_t lineNum)
{
if (funcName == nullptr) {
ZLOGE(LOG_LABEL, "invalid param, funcName is null");
return;
}
ZLOGI(LOG_LABEL, "[%{public}s %{public}zu %{public}u]: DataSize:%{public}zu, WP:%{public}zu, RP:%{public}zu",
funcName, lineNum, ProcessSkeleton::ConvertAddr(this), GetDataSize(), GetWritePosition(), GetReadPosition());
std::string format;
size_t idx = 0;
size_t size = GetOffsetsSize();
auto objOffsets = reinterpret_cast<binder_size_t *>(GetObjectOffsets());
while (idx < size) {
format += std::to_string(objOffsets[idx]) + ',';
++idx;
}
ZLOGI(LOG_LABEL, "[%{public}s %{public}zu %{public}u]: ObjSize:%{public}zu, ObjOffsets:%{public}s",
funcName, lineNum, ProcessSkeleton::ConvertAddr(this), size, format.c_str());
format.clear();
idx = 0;
size = GetDataSize();
auto data = reinterpret_cast<const uint8_t *>(GetData());
while (idx < size) {
format += std::to_string(data[idx]) + ',';
++idx;
}
ZLOGI(LOG_LABEL, "[%{public}s %{public}zu %{public}u]: data:%{public}s", funcName, lineNum,
ProcessSkeleton::ConvertAddr(this), format.c_str());
}
} // namespace OHOS

View File

@ -21,6 +21,7 @@
#include "check_instance_exit.h"
#include "ipc_debug.h"
#include "log_tags.h"
#include "securec.h"
#include "string_ex.h"
namespace OHOS {
@ -350,4 +351,33 @@ uint32_t ProcessSkeleton::ConvertAddr(const void *ptr)
}
return static_cast<uint32_t>((reinterpret_cast<uintptr_t>(ptr)) & IPC_OBJECT_MASK);
}
bool ProcessSkeleton::FlattenDBinderData(Parcel &parcel, const dbinder_negotiation_data *&dbinderData)
{
size_t start = parcel.GetWritePosition();
binder_buffer_object obj;
obj.hdr.type = BINDER_TYPE_PTR;
obj.flags = BINDER_BUFFER_FLAG_HAS_DBINDER;
obj.buffer = reinterpret_cast<binder_uintptr_t>(dbinderData);
obj.length = sizeof(dbinder_negotiation_data);
if (!parcel.WriteBuffer(&obj, sizeof(binder_buffer_object))) {
ZLOGE(LOG_LABEL, "WriteBuffer fail");
return false;
}
size_t stop = parcel.GetWritePosition();
ZLOGD(LOG_LABEL, "serialization:%{public}zu sizeof:%{public}zu", stop - start, sizeof(binder_buffer_object));
return true;
}
bool ProcessSkeleton::UnFlattenDBinderData(Parcel &parcel, dbinder_negotiation_data *&dbinderData)
{
auto *buf = parcel.ReadBuffer(sizeof(binder_buffer_object), false);
if (buf == nullptr) {
return false;
}
auto obj = reinterpret_cast<const binder_buffer_object *>(buf);
auto ret = memcpy_s(dbinderData, sizeof(dbinder_negotiation_data),
reinterpret_cast<const void *>(obj->buffer), obj->length);
return (ret == EOK);
}
} // namespace OHOS

View File

@ -140,7 +140,7 @@ private:
int TransactWithDriver(bool doRead = true);
bool WriteTransaction(int cmd, uint32_t flags, int32_t handle, uint32_t code, const MessageParcel &data,
const int *status);
const int *status, size_t totalDBinderBufSize);
int WaitForCompletion(MessageParcel *reply = nullptr, int32_t *acquireResult = nullptr);
@ -209,6 +209,12 @@ private:
#ifndef CONFIG_IPC_SINGLE
bool AddCommAuth(int32_t handle, flat_binder_object *flat);
bool TranslateDBinderStub(int handle, MessageParcel &parcel, bool isReply, size_t &totalDBinderBufSize);
bool GetDBinderCallingPidUid(int handle, bool isReply, pid_t &pid, uid_t &uid);
bool UnFlattenDBinderObject(Parcel &parcel, dbinder_negotiation_data &dbinderData);
#endif
#ifdef CONFIG_ACTV_BINDER

View File

@ -98,6 +98,8 @@ public:
virtual int OnSendRawData(std::shared_ptr<T> session, const void *data, size_t size) = 0;
bool CheckTransactionData(const dbinder_transaction_data *tr) const;
std::mutex &GetObjectMutex();
void PrintDBinderTransaction(const char *funcName, const char *titleName, const dbinder_transaction_data *tr);
void PrintBuffer(const char *funcName, const char *titleName, const uint8_t *data, size_t length);
private:
uint32_t TranslateBinderType(flat_binder_object *binderObject, char *sessionOffset, std::shared_ptr<T> session);
@ -122,6 +124,8 @@ private:
std::shared_ptr<dbinder_transaction_data> ProcessNormalData(std::shared_ptr<T> sessionObject, MessageParcel &data,
int32_t handle, int32_t socketId, uint64_t seqNum, int cmd, __u32 code, __u32 flags, int status);
bool MoveTransData2Buffer(std::shared_ptr<T> sessionObject, std::shared_ptr<dbinder_transaction_data> transData);
bool RemoveDBinderPtrData(std::shared_ptr<dbinder_transaction_data> transData, uint32_t &cutCount);
void OverrideMessageParcelData(std::shared_ptr<dbinder_transaction_data> tr, MessageParcel &data);
bool MoveMessageParcel2TransData(MessageParcel &data, std::shared_ptr<T> sessionObject,
std::shared_ptr<dbinder_transaction_data> transData, int32_t socketId, int status);
std::shared_ptr<ThreadProcessInfo> MakeThreadProcessInfo(int32_t socketId, const char *buffer, uint32_t size);

View File

@ -258,45 +258,6 @@ void DBinderBaseInvoker<T>::ConstructTransData(MessageParcel &data, dbinder_tran
transData.offsets = 0;
}
template <class T>
bool DBinderBaseInvoker<T>::MoveMessageParcel2TransData(MessageParcel &data, std::shared_ptr<T> sessionObject,
std::shared_ptr<dbinder_transaction_data> transData, int32_t socketId, int status)
{
if (data.GetDataSize() > 0) {
/* Send this parcel's data through the socket. */
transData->buffer_size = data.GetDataSize();
uint32_t useSize = transData->sizeOfSelf - sizeof(dbinder_transaction_data);
int memcpyResult =
memcpy_s(transData->buffer, useSize, reinterpret_cast<void *>(data.GetData()), transData->buffer_size);
if (data.GetOffsetsSize() > 0) {
memcpyResult += memcpy_s(transData->buffer + transData->buffer_size, useSize - transData->buffer_size,
reinterpret_cast<void *>(data.GetObjectOffsets()), data.GetOffsetsSize() * sizeof(binder_size_t));
}
if (memcpyResult != 0) {
ZLOGE(LOG_LABEL, "parcel data memcpy_s failed, socketId:%{public}d", socketId);
return false;
}
transData->offsets_size = data.GetOffsetsSize() * sizeof(binder_size_t);
transData->offsets = transData->buffer_size;
if (!CheckTransactionData(transData.get())) {
ZLOGE(LOG_LABEL, "check trans data fail, socketId:%{public}d", socketId);
return false;
}
if (!IRemoteObjectTranslateWhenSend(reinterpret_cast<char *>(transData->buffer), transData->buffer_size,
data, socketId, sessionObject)) {
ZLOGE(LOG_LABEL, "translate object failed, socketId:%{public}d", socketId);
return false;
}
} else {
transData->flags |= TF_STATUS_CODE;
transData->buffer_size = sizeof(binder_size_t);
transData->offsets_size = static_cast<binder_size_t>(status);
transData->offsets = transData->buffer_size;
}
return true;
}
template <class T>
bool DBinderBaseInvoker<T>::TranslateRawData(char *dataBuffer, MessageParcel &data, uint32_t socketId)
{

View File

@ -89,7 +89,7 @@ template <class T> void DBinderBaseInvoker<T>::ProcessTransaction(dbinder_transa
option.SetFlags(flags);
// cannot use stub any more after SendRequest because this cmd may be
// dbinder dec ref and thus stub will be destroyed
int error = stubObject->SendRequest(tr->code, data, reply, option);
error = stubObject->SendRequest(tr->code, data, reply, option);
if (error != ERR_NONE) {
ZLOGW(LOG_LABEL, "stub sendrequest failed, cmd:%{public}u error:%{public}d "
"listenFd:%{public}d seq:%{public}" PRIu64, tr->code, error, listenFd, senderSeqNumber);
@ -265,5 +265,140 @@ std::shared_ptr<ThreadProcessInfo> DBinderBaseInvoker<T>::MakeThreadProcessInfo(
return processInfo;
}
template <class T>
bool DBinderBaseInvoker<T>::RemoveDBinderPtrData(std::shared_ptr<dbinder_transaction_data> tr, uint32_t &cutCount)
{
size_t i = 0;
size_t objCount = tr->offsets_size / sizeof(binder_size_t);
while (i < objCount) {
binder_size_t *offsets = reinterpret_cast<binder_size_t *>(tr->buffer + tr->buffer_size);
auto obj = reinterpret_cast<binder_object_header *>(tr->buffer + offsets[i]);
if (obj->type == BINDER_TYPE_PTR) {
ZLOGI(LOG_LABEL, "ptr object offset:%{public}llu", offsets[i]);
// record deleted offset
binder_size_t delOffset = offsets[i];
// update these offsets that following the deleted offset
for (size_t j = i; (j + 1) < objCount; j++) {
offsets[j] = offsets[j + 1] - sizeof(binder_buffer_object);
}
// update total offsets size
tr->offsets_size -= sizeof(binder_size_t);
// remove ptr space in the buffer
size_t removeSize = tr->buffer_size + tr->offsets_size - delOffset - sizeof(binder_buffer_object);
errno_t ret = memmove_s(tr->buffer + delOffset, removeSize,
tr->buffer + delOffset + sizeof(binder_buffer_object), removeSize);
if (ret != EOK) {
ZLOGE(LOG_LABEL, "memmove fail, %{public}d", ret);
return false;
}
// update buffer size
tr->buffer_size -= sizeof(binder_buffer_object);
// update offsets
tr->offsets = tr->buffer_size;
// clear the disused buffer space
size_t delSize = sizeof(binder_size_t) + sizeof(binder_buffer_object) + T::GetFlatSessionLen();
memset_s(tr->buffer + tr->buffer_size + tr->offsets_size, delSize, 0, delSize);
// update sizeofSelf
tr->sizeOfSelf -= delSize;
++cutCount;
}
++i;
}
return true;
}
template <class T>
void DBinderBaseInvoker<T>::OverrideMessageParcelData(std::shared_ptr<dbinder_transaction_data> tr, MessageParcel &data)
{
// override data(MessageParcel)
data.FlushBuffer();
data.WriteBuffer(reinterpret_cast<const void *>(tr->buffer), tr->buffer_size);
// set offsets
size_t objCount = tr->offsets_size / sizeof(binder_size_t);
if (objCount > 0) {
data.InjectOffsets(reinterpret_cast<binder_uintptr_t>(tr->buffer + tr->offsets), objCount);
}
}
template <class T>
void DBinderBaseInvoker<T>::PrintDBinderTransaction(const char *funcName, const char *titleName,
const dbinder_transaction_data *tr)
{
if (funcName == nullptr || titleName == nullptr || tr == nullptr) {
ZLOGE(LOG_LABEL, "invalid param");
return;
}
ZLOGI(LOG_LABEL, "[%{public}s %{public}s]: sizeOfSelf:%{public}u, magic:%{public}u, version:%{public}u, "
"cmd:%{public}d, code:%{public}u, flags:%{public}u, cookie:%{public}llu, seqNumber:%{public}llu, "
"buffer_size:%{public}llu, offsets_size:%{public}llu, offsets:%{public}llu, "
"sizeof(dbinder_transaction_data):%{public}zu",
funcName, titleName, tr->sizeOfSelf, tr->magic, tr->version, tr->cmd, tr->code, tr->flags, tr->cookie,
tr->seqNumber, tr->buffer_size, tr->offsets_size, tr->offsets, sizeof(dbinder_transaction_data));
}
template <class T>
void DBinderBaseInvoker<T>::PrintBuffer(const char *funcName, const char *titleName, const uint8_t *data,
size_t length)
{
std::string format;
size_t idx = 0;
while (idx < length) {
format += std::to_string(data[idx]) + ',';
++idx;
}
ZLOGI(LOG_LABEL, "[%{public}s %{public}s]: length:%{public}zu, content:%{public}s",
funcName, titleName, length, format.c_str());
}
template <class T>
bool DBinderBaseInvoker<T>::MoveMessageParcel2TransData(MessageParcel &data, std::shared_ptr<T> sessionObject,
std::shared_ptr<dbinder_transaction_data> transData, int32_t socketId, int status)
{
if (data.GetDataSize() > 0) {
/* Send this parcel's data through the socket. */
transData->buffer_size = data.GetDataSize();
uint32_t useSize = transData->sizeOfSelf - sizeof(dbinder_transaction_data);
int memcpyResult =
memcpy_s(transData->buffer, useSize, reinterpret_cast<void *>(data.GetData()), transData->buffer_size);
if (data.GetOffsetsSize() > 0) {
memcpyResult += memcpy_s(transData->buffer + transData->buffer_size, useSize - transData->buffer_size,
reinterpret_cast<void *>(data.GetObjectOffsets()), data.GetOffsetsSize() * sizeof(binder_size_t));
}
if (memcpyResult != 0) {
ZLOGE(LOG_LABEL, "parcel data memcpy_s failed, socketId:%{public}d", socketId);
return false;
}
transData->offsets_size = data.GetOffsetsSize() * sizeof(binder_size_t);
transData->offsets = transData->buffer_size;
// remove dbinder PTR data
uint32_t cutCount = 0;
if (!RemoveDBinderPtrData(transData, cutCount)) {
ZLOGE(LOG_LABEL, "RemoveDBinderPtrData fail");
return false;
}
if (cutCount > 0) {
OverrideMessageParcelData(transData, data);
}
if (!CheckTransactionData(transData.get())) {
ZLOGE(LOG_LABEL, "check trans data fail, socketId:%{public}d", socketId);
return false;
}
if (!IRemoteObjectTranslateWhenSend(reinterpret_cast<char *>(transData->buffer), transData->buffer_size,
data, socketId, sessionObject)) {
ZLOGE(LOG_LABEL, "translate object failed, socketId:%{public}d", socketId);
return false;
}
} else {
transData->flags |= TF_STATUS_CODE;
transData->buffer_size = sizeof(binder_size_t);
transData->offsets_size = static_cast<binder_size_t>(status);
transData->offsets = transData->buffer_size;
}
return true;
}
} // namespace OHOS
#endif // OHOS_IPC_DBINDER_BASE_INVOKER_PROCESS_H

View File

@ -82,6 +82,7 @@ struct binder_buffer_object {
};
enum {
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
BINDER_BUFFER_FLAG_HAS_DBINDER = 0x01 << 31,
};
struct binder_fd_array_object {
struct binder_object_header hdr;
@ -267,6 +268,8 @@ static const uint32_t PID_LEN = 32;
static const uint32_t RPC_DEFAULT_VERSION_NUM = 1;
static const uint32_t SUPPORT_TOKENID_VERSION_NUM = 2;
static const uint32_t TOKENID_MAGIC = 0X544F4B49;
static const uint32_t SESSION_NAME_LENGTH = 64;
static const uint32_t DBINDER_DESC_LENGTH = 64;
enum {
BINDER_TYPE_REMOTE_BINDER = B_PACK_CHARS('r', 'b', '*', B_TYPE_LARGE),
@ -295,6 +298,18 @@ struct dbinder_transaction_data {
binder_size_t buffer_size;
binder_size_t offsets_size;
binder_uintptr_t offsets;
unsigned char buffer[0];
unsigned char buffer[];
};
struct dbinder_negotiation_data {
__u32 proto;
__u32 tokenid;
__u64 stub_index;
char target_name[SESSION_NAME_LENGTH + 1];
char local_name[SESSION_NAME_LENGTH + 1];
char target_device[DEVICEID_LENGTH + 1];
char local_device[DEVICEID_LENGTH + 1];
char16_t desc[DBINDER_DESC_LENGTH + 1];
char reserved[3];
};
#endif // OHOS_IPC_SYS_BINDER_H

View File

@ -70,6 +70,9 @@ namespace IPC_SINGLE {
using namespace OHOS::HiviewDFX;
static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC_BINDER_INVOKER, "BinderInvoker" };
static constexpr pid_t INVALID_PID = -1;
static constexpr int32_t BINDER_ALIGN_BYTES = 8;
enum {
GET_SERVICE_TRANSACTION = 0x1,
CHECK_SERVICE_TRANSACTION,
@ -141,17 +144,26 @@ int BinderInvoker::SendRequest(int handle, uint32_t code, MessageParcel &data, M
{
int error = ERR_NONE;
uint32_t flags = static_cast<uint32_t>(option.GetFlags());
MessageParcel &newData = const_cast<MessageParcel &>(data);
size_t oldWritePosition = newData.GetWritePosition();
HiTraceId traceId = HiTraceChain::GetId();
// set client send trace point if trace is enabled
HiTraceId childId = HitraceInvoker::TraceClientSend(handle, code, newData, flags, traceId);
[[maybe_unused]] ThreadMigrationDisabler _d;
if (!TranslateDBinderProxy(handle, data)) {
return IPC_INVOKER_WRITE_TRANS_ERR;
}
if (!WriteTransaction(BC_TRANSACTION, flags, handle, code, data, nullptr)) {
newData.RewindWrite(oldWritePosition);
size_t totalDBinderBufSize = 0;
#ifndef CONFIG_IPC_SINGLE
if (!TranslateDBinderStub(handle, data, false, totalDBinderBufSize)) {
return IPC_TRANSLATE_DBINDER_STUB_ERR;
}
auto dataSize = data.GetDataSize();
if (totalDBinderBufSize > 0 && dataSize % BINDER_ALIGN_BYTES != 0) {
ZLOGI(LABEL, "not 8 bytes aligned(%{public}zu), padding it", dataSize);
data.WriteInt8(0);
}
#endif
int cmd = (totalDBinderBufSize > 0) ? BC_TRANSACTION_SG : BC_TRANSACTION;
if (!WriteTransaction(cmd, flags, handle, code, data, nullptr, totalDBinderBufSize)) {
ZLOGE(LABEL, "WriteTransaction ERROR");
return IPC_INVOKER_WRITE_TRANS_ERR;
}
@ -167,9 +179,6 @@ int BinderInvoker::SendRequest(int handle, uint32_t code, MessageParcel &data, M
ffrt_this_task_set_legacy_mode(false);
#endif
}
HitraceInvoker::TraceClientReceieve(handle, code, flags, traceId, childId);
// restore Parcel data
newData.RewindWrite(oldWritePosition);
return error;
}
@ -342,7 +351,106 @@ bool BinderInvoker::AddCommAuth(int32_t handle, flat_binder_object *flat)
return true;
}
bool BinderInvoker::GetDBinderCallingPidUid(int handle, bool isReply, pid_t &pid, uid_t &uid)
{
if (pid == INVALID_PID) {
if (!isReply) {
MessageParcel data;
MessageParcel reply;
MessageOption option;
auto ret = SendRequest(handle, GET_PID_UID, data, reply, option);
if (ret != ERR_NONE) {
ZLOGE(LABEL, "GET_PID_UID failed, error:%{public}d", ret);
return false;
}
pid = reply.ReadUint32();
uid = reply.ReadUint32();
} else {
pid = GetCallerPid();
uid = GetCallerUid();
}
ZLOGI(LABEL, "pid:%{public}d uid:%{public}d", pid, uid);
}
return true;
}
bool BinderInvoker::TranslateDBinderStub(int handle, MessageParcel &parcel, bool isReply, size_t &totalDBinderBufSize)
{
pid_t pid = INVALID_PID;
uid_t uid = INVALID_PID;
uintptr_t dataBuf = parcel.GetData();
size_t totalSize = parcel.GetDataSize();
size_t objCount = parcel.GetOffsetsSize();
binder_size_t *objOffset = reinterpret_cast<binder_size_t *>(parcel.GetObjectOffsets());
size_t alignSize = 0;
for (size_t i = 0; i < objCount; ++i) {
auto obj = reinterpret_cast<binder_buffer_object *>(dataBuf + objOffset[i]);
if ((obj->hdr.type == BINDER_TYPE_PTR) && (obj->length == sizeof(dbinder_negotiation_data))) {
alignSize = (obj->length + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1);
if (alignSize != obj->length) {
ZLOGW(LABEL, "alignSize(%{public}zu) != obj.length(%{public}llu)", alignSize, obj->length);
}
totalDBinderBufSize += alignSize;
// skip to next object
++i;
if ((i >= objCount) || (objOffset[i] + sizeof(flat_binder_object) > totalSize)) {
ZLOGW(LABEL, "over length, i:%{public}zu count:%{public}zu offset:%{public}llu totalSize:%{public}zu",
i, objCount, objOffset[i], totalSize);
break;
}
auto flat = reinterpret_cast<flat_binder_object *>(dataBuf + objOffset[i]);
if (flat->hdr.type != BINDER_TYPE_BINDER) {
ZLOGE(LABEL, "unexpected binder type:%{public}d", flat->hdr.type);
return false;
}
if (!GetDBinderCallingPidUid(handle, isReply, pid, uid)) {
ZLOGE(LABEL, "GetDBinderCallingPidUid fail, cookie:%{public}llu", flat->cookie);
return false;
}
auto stub = reinterpret_cast<IPCObjectStub *>(flat->cookie);
if (stub->GetAndSaveDBinderData(pid, uid) != ERR_NONE) {
ZLOGE(LABEL, "GetAndSaveDBinderData fail, cookie:%{public}llu", flat->cookie);
return false;
}
ZLOGI(LABEL, "succ, cookie:%{public}llu", flat->cookie);
}
}
return true;
}
bool BinderInvoker::UnFlattenDBinderObject(Parcel &parcel, dbinder_negotiation_data &dbinderData)
{
auto offset = parcel.GetReadPosition();
auto *buffer = parcel.ReadBuffer(sizeof(binder_object_header), false);
if (buffer == nullptr) {
ZLOGE(LABEL, "null object buffer");
return false;
}
auto *hdr = reinterpret_cast<const binder_object_header *>(buffer);
if (hdr->type != BINDER_TYPE_PTR) {
parcel.RewindRead(offset);
return false;
}
ZLOGI(LABEL, "PTR");
parcel.RewindRead(offset);
buffer = parcel.ReadBuffer(sizeof(binder_buffer_object), false);
if (buffer == nullptr) {
ZLOGE(LABEL, "null object buffer");
return false;
}
auto *obj = reinterpret_cast<const binder_buffer_object *>(buffer);
if (((obj->flags & BINDER_BUFFER_FLAG_HAS_DBINDER) == 0) || (obj->length != sizeof(dbinder_negotiation_data))) {
ZLOGW(LABEL, "no dbinder buffer flag");
parcel.RewindRead(offset);
return false;
}
dbinderData = *reinterpret_cast<dbinder_negotiation_data *>(obj->buffer);
return true;
}
#endif
bool BinderInvoker::SetMaxWorkThread(int maxThreadNum)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
@ -424,11 +532,23 @@ void BinderInvoker::StartWorkLoop()
int BinderInvoker::SendReply(MessageParcel &reply, uint32_t flags, int32_t result)
{
int error = WriteTransaction(BC_REPLY, flags, -1, 0, reply, &result);
size_t totalDBinderBufSize = 0;
#ifndef CONFIG_IPC_SINGLE
if (!TranslateDBinderStub(-1, reply, true, totalDBinderBufSize)) {
return IPC_TRANSLATE_DBINDER_STUB_ERR;
}
auto replySize = reply.GetDataSize();
if (totalDBinderBufSize > 0 && replySize % BINDER_ALIGN_BYTES != 0) {
ZLOGI(LABEL, "not 8 bytes aligned(%{public}zu), padding it", replySize);
reply.WriteInt8(0);
}
#endif
int cmd = (totalDBinderBufSize > 0) ? BC_REPLY_SG : BC_REPLY;
int error = WriteTransaction(cmd, flags, -1, 0, reply, &result, totalDBinderBufSize);
if (error < ERR_NONE) {
return error;
}
return WaitForCompletion();
}
@ -657,13 +777,10 @@ void BinderInvoker::Transaction(binder_transaction_data_secctx& trSecctx)
if (tr.offsets_size > 0) {
data->InjectOffsets(tr.data.ptr.offsets, tr.offsets_size / sizeof(binder_size_t));
}
uint32_t &newflags = const_cast<uint32_t &>(tr.flags);
int isServerTraced = HitraceInvoker::TraceServerReceieve(static_cast<uint64_t>(tr.target.handle),
tr.code, *data, newflags);
InvokerProcInfo oldInvokerProcInfo = {
callerPid_, callerRealPid_, callerUid_, callerTokenID_, firstTokenID_, callerSid_, 0 };
uint32_t oldStatus = status_;
callerSid_ = (trSecctx.secctx != 0) ? reinterpret_cast<char *>(trSecctx.secctx) : "";
callerPid_ = tr.sender_pid;
callerUid_ = tr.sender_euid;
@ -681,8 +798,6 @@ void BinderInvoker::Transaction(binder_transaction_data_secctx& trSecctx)
SetStatus(IRemoteInvoker::ACTIVE_INVOKER);
int32_t error = TargetStubSendRequest(tr, *data, reply, option, flagValue);
HitraceInvoker::TraceServerSend(static_cast<uint64_t>(tr.target.handle), tr.code, isServerTraced, newflags);
if (!(flagValue & TF_ONE_WAY)) {
SendReply(reply, 0, error);
}
@ -881,6 +996,7 @@ int BinderInvoker::HandleCommands(uint32_t cmd)
void BinderInvoker::JoinThread(bool initiative)
{
[[maybe_unused]] ThreadMigrationDisabler _d;
isMainWorkThread = initiative;
output_.WriteUint32(initiative ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
StartWorkLoop();
@ -948,9 +1064,12 @@ int BinderInvoker::TransactWithDriver(bool doRead)
}
bool BinderInvoker::WriteTransaction(int cmd, uint32_t flags, int32_t handle, uint32_t code, const MessageParcel &data,
const int32_t *status)
const int32_t *status, size_t totalDBinderBufSize)
{
binder_transaction_data tr {};
binder_transaction_data_sg tr_sg {};
auto &tr = tr_sg.transaction_data;
bool isContainPtrType = totalDBinderBufSize > 0;
tr.target.handle = (uint32_t)handle;
tr.code = code;
tr.flags = flags;
@ -961,6 +1080,7 @@ bool BinderInvoker::WriteTransaction(int cmd, uint32_t flags, int32_t handle, ui
tr.data.ptr.buffer = (binder_uintptr_t)data.GetData();
tr.offsets_size = data.GetOffsetsSize() * sizeof(binder_size_t);
tr.data.ptr.offsets = data.GetObjectOffsets();
tr_sg.buffers_size = isContainPtrType ? totalDBinderBufSize : 0;
} else if (status != nullptr) {
// Send this parcel's status through the binder.
tr.flags |= TF_STATUS_CODE;
@ -971,10 +1091,12 @@ bool BinderInvoker::WriteTransaction(int cmd, uint32_t flags, int32_t handle, ui
}
if (!output_.WriteInt32(cmd)) {
ZLOGE(LABEL, "WriteTransaction Command failure");
ZLOGE(LABEL, "write cmd fail");
return false;
}
return output_.WriteBuffer(&tr, sizeof(binder_transaction_data));
const void *buf = isContainPtrType ? static_cast<const void *>(&tr_sg) : static_cast<const void *>(&tr);
size_t bufSize = isContainPtrType ? sizeof(tr_sg) : sizeof(tr);
return output_.WriteBuffer(buf, bufSize);
}
void BinderInvoker::OnTransactionComplete(
@ -1311,6 +1433,16 @@ bool BinderInvoker::FlattenObject(Parcel &parcel, const IRemoteObject *object) c
sptr<IRemoteObject> BinderInvoker::UnflattenObject(Parcel &parcel)
{
#ifndef CONFIG_IPC_SINGLE
auto offset = parcel.GetReadPosition();
dbinder_negotiation_data dbinderData;
bool isDBinderObj = UnFlattenDBinderObject(parcel, dbinderData);
auto offset2 = parcel.GetReadPosition();
if (offset != offset2) {
ZLOGW(LABEL, "offset:%{public}zu offset2:%{public}zu isDBinderObj:%{public}d",
offset, offset2, isDBinderObj);
}
#endif
const uint8_t *buffer = parcel.ReadBuffer(sizeof(flat_binder_object), false);
if (buffer == nullptr) {
ZLOGE(LABEL, "null object buffer");
@ -1330,7 +1462,14 @@ sptr<IRemoteObject> BinderInvoker::UnflattenObject(Parcel &parcel)
break;
}
case BINDER_TYPE_HANDLE: {
#ifndef CONFIG_IPC_SINGLE
if (isDBinderObj) {
ZLOGI(LABEL, "dbinder BINDER_TYPE_HANDLE");
}
remoteObject = current->FindOrNewObject(flat->handle, isDBinderObj ? &dbinderData : nullptr);
#else
remoteObject = current->FindOrNewObject(flat->handle);
#endif
break;
}
default:
@ -1339,9 +1478,8 @@ sptr<IRemoteObject> BinderInvoker::UnflattenObject(Parcel &parcel)
}
if (!current->IsContainsObject(remoteObject)) {
remoteObject = nullptr;
}
remoteObject = nullptr;
}
return remoteObject;
}

View File

@ -24,6 +24,8 @@ ohos_unittest("IPCNativeUnitTest") {
include_dirs = [
"$IPC_CORE_ROOT/c/rpc/include",
"$IPC_CORE_ROOT/c/ipc_adapter/include",
"$IPC_CORE_ROOT/src/core/include",
"$IPC_CORE_ROOT/src/mock/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/libdbinder/include",
"$SUBSYSTEM_DIR/native/src/core/include",
@ -79,7 +81,7 @@ ohos_unittest("IPCFileDescOpsTest") {
"$IPC_CORE_ROOT/c/ipc_adapter/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/libdbinder/include",
"$SUBSYSTEM_DIR/native/src/core/include",
"$SUBSYSTEM_DIR/ipc/native/src/core/include",
]
sources = [ "ipc_file_desc_unittest.cpp" ]
@ -187,7 +189,10 @@ if (support_jsapi) {
ohos_unittest("IPCNapiUnitTest") {
module_out_path = MODULE_OUTPUT_PATH
include_dirs = [ "$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include" ]
include_dirs = [
"$IPC_CORE_ROOT/src/mock/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/ipc_core/include",
]
sources = [ "ipc_napi_unittest.cpp" ]
configs = []

View File

@ -16,6 +16,7 @@
#include "dbinder_service_stub.h"
#include <cinttypes>
#include "securec.h"
#include "sys_binder.h"
#include "string_ex.h"
@ -24,6 +25,8 @@
#include "dbinder_log.h"
#include "dbinder_service.h"
#include "ipc_skeleton.h"
#include "ipc_thread_skeleton.h"
#include "process_skeleton.h"
namespace OHOS {
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC_DBINDER_SER_STUB,
@ -35,12 +38,17 @@ DBinderServiceStub::DBinderServiceStub(const std::string &service, const std::st
{
DBINDER_LOGD(LOG_LABEL, "created, service:%{public}s device:%{public}s",
serviceName_.c_str(), DBinderService::ConvertToSecureDeviceID(deviceID_).c_str());
dbinderData_ = std::make_unique<uint8_t[]>(sizeof(dbinder_negotiation_data));
if (dbinderData_ == nullptr) {
DBINDER_LOGW(LOG_LABEL, "malloc dbinderData_ fail");
}
}
DBinderServiceStub::~DBinderServiceStub()
{
DBINDER_LOGD(LOG_LABEL, "destroyed, service:%{public}s device:%{public}s",
serviceName_.c_str(), DBinderService::ConvertToSecureDeviceID(deviceID_).c_str());
dbinderData_ = nullptr;
}
const std::string &DBinderServiceStub::GetServiceName()
@ -233,4 +241,137 @@ int32_t DBinderServiceStub::RemoveDbinderDeathRecipient(MessageParcel &data, Mes
}
return ERR_NONE;
}
bool DBinderServiceStub::Marshalling(Parcel &parcel) const
{
DBINDER_LOGD(LOG_LABEL, "enter");
if (dbinderData_ == nullptr) {
DBINDER_LOGE(LOG_LABEL, "dbinderData_ is nullptr");
return false;
}
auto *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker == nullptr) {
DBINDER_LOGE(LOG_LABEL, "GetRemoteInvoker fail");
return false;
}
size_t offset = parcel.GetWritePosition();
auto dbinderData = reinterpret_cast<const dbinder_negotiation_data *>(dbinderData_.get());
if (!ProcessSkeleton::FlattenDBinderData(parcel, dbinderData)) {
return false;
}
if (!invoker->FlattenObject(parcel, this)) {
DBINDER_LOGE(LOG_LABEL, "FlattenObject fail");
parcel.RewindWrite(offset);
return false;
}
return true;
}
bool DBinderServiceStub::Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object)
{
DBINDER_LOGD(LOG_LABEL, "enter");
auto serviceStub = reinterpret_cast<DBinderServiceStub *>(object.GetRefPtr());
if (serviceStub == nullptr) {
return false;
}
return serviceStub->Marshalling(parcel);
}
int DBinderServiceStub::SaveDBinderData(const std::string &localBusName)
{
sptr<DBinderService> dBinderService = DBinderService::GetInstance();
if (dBinderService == nullptr) {
DBINDER_LOGE(LOG_LABEL, "DBinderService is nullptr");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SERVICE_NULL, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
auto session = dBinderService->QuerySessionObject(reinterpret_cast<binder_uintptr_t>(this));
if (session == nullptr) {
DBINDER_LOGE(LOG_LABEL, "client find session is null");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_QUERY_SESSION_FAIL, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
if (dbinderData_ == nullptr) {
DBINDER_LOGE(LOG_LABEL, "dbinderData_ is nullptr");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
return DBINDER_SERVICE_MALLOC_ERR;
}
dbinder_negotiation_data *dbinderData = reinterpret_cast<dbinder_negotiation_data *>(dbinderData_.get());
dbinderData->proto = IRemoteObject::IF_PROT_DATABUS;
dbinderData->stub_index = session->stubIndex;
dbinderData->tokenid = session->deviceIdInfo.tokenId;
auto ret = memcpy_s(dbinderData->target_name, SESSION_NAME_LENGTH, session->serviceName.c_str(),
session->serviceName.length());
ret += memcpy_s(dbinderData->target_device, DEVICEID_LENGTH, session->deviceIdInfo.toDeviceId,
DEVICEID_LENGTH);
ret += memcpy_s(dbinderData->local_device, DEVICEID_LENGTH, session->deviceIdInfo.fromDeviceId,
DEVICEID_LENGTH);
ret += memcpy_s(dbinderData->local_name, SESSION_NAME_LENGTH, localBusName.c_str(), localBusName.length());
ret += memcpy_s(dbinderData->desc, DBINDER_DESC_LENGTH, descriptor_.c_str(), descriptor_.length());
if (ret != EOK) {
DBINDER_LOGE(LOG_LABEL, "memcpy_s fail, ret:%{public}d", ret);
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_ERR_MEMCPY_DATA, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
DBINDER_LOGI(LOG_LABEL, "proto:%{public}d stubIndex:%{public}llu tokenid:%{public}u "
"targetName:%{public}s localName:%{public}s",
dbinderData->proto, dbinderData->stub_index, dbinderData->tokenid, dbinderData->target_name,
dbinderData->local_name);
return ERR_NONE;
}
bool DBinderServiceStub::CheckSessionObjectValidity()
{
sptr<DBinderService> dBinderService = DBinderService::GetInstance();
if (dBinderService == nullptr) {
DBINDER_LOGE(LOG_LABEL, "DBinderService is nullptr");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SERVICE_NULL, __FUNCTION__);
return false;
}
auto session = dBinderService->QuerySessionObject(reinterpret_cast<binder_uintptr_t>(this));
if (session == nullptr) {
DBINDER_LOGE(LOG_LABEL, "client find session is null");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_QUERY_SESSION_FAIL, __FUNCTION__);
return false;
}
if (session->type != IRemoteObject::DATABUS_TYPE) {
DBINDER_LOGE(LOG_LABEL, "Invalid Type:%{public}d", session->type);
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_TYPE_INVALID, __FUNCTION__);
return false;
}
return true;
}
int DBinderServiceStub::GetAndSaveDBinderData(pid_t pid, uid_t uid)
{
int result = ERR_NONE;
if (uid < 0 || pid < 0) {
DBINDER_LOGE(LOG_LABEL, "uid(%{public}d) or pid(%{public}d) is invalid", uid, pid);
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_UID_OR_PID_FAIL, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
if (!CheckSessionObjectValidity()) {
return DBINDER_SERVICE_FILL_DATA_ERR;
}
sptr<DBinderService> dBinderService = DBinderService::GetInstance();
if (dBinderService == nullptr) {
DBINDER_LOGE(LOG_LABEL, "DBinderService is nullptr");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_GET_SERVICE_NULL, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
std::string localBusName = dBinderService->CreateDatabusName(uid, pid);
if (localBusName.empty()) {
DBINDER_LOGE(LOG_LABEL, "local busname nil");
DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_CREATE_BUS_NAME_FAIL, __FUNCTION__);
return DBINDER_SERVICE_FILL_DATA_ERR;
}
return SaveDBinderData(localBusName);
}
} // namespace OHOS