fix:convert string to integer crash

Signed-off-by: yueyan <yueyan8@huawei.com>
This commit is contained in:
yueyan 2024-11-12 23:19:46 +08:00
parent dc8fe18aaf
commit 069259486e
8 changed files with 338 additions and 36 deletions

View File

@ -49,6 +49,8 @@ public:
static bool UnFlattenDBinderData(Parcel &parcel, dbinder_negotiation_data *&dbinderData);
static bool GetSubStr(const std::string &str, std::string &substr, size_t offset, size_t length);
static bool IsNumStr(const std::string &str);
static bool StrToUint64(const std::string &str, uint64_t &value);
static bool StrToInt32(const std::string &str, int32_t &value);
bool SetIPCProxyLimit(uint64_t num, std::function<void (uint64_t num)> callback);
sptr<IRemoteObject> GetRegistryObject();

View File

@ -28,7 +28,7 @@
namespace OHOS {
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_COMMON, "ProcessSkeleton" };
static constexpr int PRINT_ERR_CNT = 100;
static constexpr int DEC_BASE = 10;
#ifdef __aarch64__
static constexpr uint32_t IPC_OBJECT_MASK = 0xffffffff;
#else
@ -135,7 +135,7 @@ bool ProcessSkeleton::DetachObject(IRemoteObject *object, const std::u16string &
}
if (iterator->second.GetRefPtr() != object) {
ZLOGI(LOG_LABEL, "can not erase it because addr if different, "
ZLOGI(LOG_LABEL, "can not erase it because addr is different, "
"desc:%{public}s, recorded object:%{public}u, detach object:%{public}u",
ConvertToSecureDesc(Str16ToStr8(descriptor)).c_str(), ConvertAddr(iterator->second.GetRefPtr()),
ConvertAddr(object));
@ -411,6 +411,55 @@ bool ProcessSkeleton::IsNumStr(const std::string &str)
return std::all_of(str.begin(), str.end(), ::isdigit);
}
template<typename V, typename F>
static bool StrToInteger(const std::string &str, V &value, F func)
{
if (str.empty()) {
ZLOGE(LOG_LABEL, "empty input");
return false;
}
const char *begin = str.c_str();
char *end = nullptr;
errno = 0;
V valueTmp = func(begin, &end, DEC_BASE);
if (errno == ERANGE) {
ZLOGE(LOG_LABEL, "out of range");
return false;
}
if (end == begin || end[0] != '\0') {
ZLOGE(LOG_LABEL, "illegal input");
return false;
}
value = valueTmp;
return true;
}
bool ProcessSkeleton::StrToUint64(const std::string &str, uint64_t &value)
{
uint64_t valueTmp = 0;
if (!StrToInteger(str, valueTmp, strtoull)) {
return false;
}
value = valueTmp;
return true;
}
bool ProcessSkeleton::StrToInt32(const std::string &str, int32_t &value)
{
int64_t valueTmp = 0;
if (!StrToInteger(str, valueTmp, strtoll)) {
return false;
}
if ((valueTmp < INT32_MIN || valueTmp > INT32_MAX)) {
ZLOGE(LOG_LABEL, "out of range, str:%{public}s", str.c_str());
return false;
}
value = static_cast<int32_t>(valueTmp);
return true;
}
bool ProcessSkeleton::GetThreadStopFlag()
{
return stopThreadFlag_.load();

View File

@ -271,6 +271,10 @@ private:
}
#endif // CONFIG_ACTV_BINDER
bool GetUint64ValueByStrSlice(const std::string &str, size_t offset, size_t length, uint64_t &value);
bool GetCallerRealPidByStr(const std::string &str, size_t offset, size_t length, pid_t &callerRealPid);
bool GetCallerPidAndUidByStr(const std::string &str, size_t offset, pid_t &pid, pid_t &uid);
private:
DISALLOW_COPY_AND_MOVE(BinderInvoker);
static constexpr int IPC_DEFAULT_PARCEL_SIZE = 256;

View File

@ -1651,45 +1651,39 @@ bool BinderInvoker::SetCallingIdentity(std::string &identity, bool flag)
if (identity.empty() || identity.length() <= ACCESS_TOKEN_MAX_LEN) {
return false;
}
PrintIdentity(flag, true);
auto pos = identity.find('<');
if (pos == std::string::npos) {
ZLOGE(LABEL, "invliad identity");
return false;
}
PrintIdentity(flag, true);
std::string callerSid;
if (!ProcessSkeleton::GetSubStr(identity, callerSid, 0, pos)) {
ZLOGE(LABEL, "Identity param callerSid is invalid");
std::string callerSidStr;
if (!ProcessSkeleton::GetSubStr(identity, callerSidStr, 0, pos)) {
ZLOGE(LABEL, "get caller sid fail");
return false;
}
std::string tokenIdStr;
if (!ProcessSkeleton::GetSubStr(identity, tokenIdStr, pos + 1, ACCESS_TOKEN_MAX_LEN) ||
!ProcessSkeleton::IsNumStr(tokenIdStr)) {
ZLOGE(LABEL, "Identity param tokenId is invalid");
uint64_t callerTokenIdTmp = 0;
if (!GetUint64ValueByStrSlice(identity, pos + 1, ACCESS_TOKEN_MAX_LEN, callerTokenIdTmp)) {
ZLOGE(LABEL, "convert callerTokenId fail");
return false;
}
std::string realPidStr;
if (!ProcessSkeleton::GetSubStr(identity, realPidStr, pos + 1 + ACCESS_TOKEN_MAX_LEN, ACCESS_TOKEN_MAX_LEN) ||
!ProcessSkeleton::IsNumStr(realPidStr)) {
ZLOGE(LABEL, "Identity param realPid is invalid");
pid_t callerRealPidTmp = 0;
if (!GetCallerRealPidByStr(identity, pos + 1 + ACCESS_TOKEN_MAX_LEN, ACCESS_TOKEN_MAX_LEN, callerRealPidTmp)) {
ZLOGE(LABEL, "convert callerRealPid fail");
return false;
}
std::string pidUidStr;
pid_t callerPidTmp = 0;
pid_t callerUidTmp = 0;
size_t offset = pos + 1 + ACCESS_TOKEN_MAX_LEN * PIDUID_OFFSET;
if (identity.length() <= offset) {
ZLOGE(LABEL, "Identity param no pidUid, len:%{public}zu, offset:%{public}zu", identity.length(), offset);
if (!GetCallerPidAndUidByStr(identity, offset, callerPidTmp, callerUidTmp)) {
ZLOGE(LABEL, "convert callerPid and callerUid fail");
return false;
}
size_t subLen = identity.length() - offset;
if (!ProcessSkeleton::GetSubStr(identity, pidUidStr, offset, subLen) || !ProcessSkeleton::IsNumStr(pidUidStr)) {
ZLOGE(LABEL, "Identity param pidUid is invalid");
return false;
}
callerSid_ = callerSid;
callerTokenID_ = std::stoull(tokenIdStr.c_str());
callerRealPid_ = static_cast<int>(std::stoull(realPidStr.c_str()));
uint64_t pidUid = std::stoull(pidUidStr.c_str());
callerUid_ = static_cast<int>(pidUid >> PID_LEN);
callerPid_ = static_cast<int>(pidUid);
callerSid_ = callerSidStr;
callerTokenID_ = callerTokenIdTmp;
callerRealPid_ = callerRealPidTmp;
callerPid_ = callerPidTmp;
callerUid_ = callerUidTmp;
PrintIdentity(flag, false);
return true;
}
@ -1825,6 +1819,82 @@ bool BinderInvoker::IsActvBinderService()
}
#endif // CONFIG_ACTV_BINDER
bool BinderInvoker::GetUint64ValueByStrSlice(const std::string &str, size_t offset, size_t length, uint64_t &value)
{
if (str.length() < offset + length) {
ZLOGE(LABEL, "illegal param, len:%{public}zu, offset:%{public}zu, length:%{public}zu", str.length(), offset,
length);
return false;
}
std::string subStr;
if (!ProcessSkeleton::GetSubStr(str, subStr, offset, length)) {
ZLOGE(LABEL, "get subStr fail");
return false;
}
uint64_t valueTmp = 0;
if (!ProcessSkeleton::StrToUint64(subStr, valueTmp)) {
ZLOGE(LABEL, "convert integer fail, substr:%{public}s", subStr.c_str());
return false;
}
value = valueTmp;
return true;
}
bool BinderInvoker::GetCallerRealPidByStr(const std::string &str, size_t offset, size_t length, pid_t &callerRealPid)
{
if (str.length() < offset + length) {
ZLOGE(LABEL, "illegal param, len:%{public}zu, offset:%{public}zu, length:%{public}zu", str.length(), offset,
length);
return false;
}
std::string realPidStr;
if (!ProcessSkeleton::GetSubStr(str, realPidStr, offset, length)) {
ZLOGE(LABEL, "get realPidStr fail");
return false;
}
int32_t callerRealPidTmp = 0;
if (!ProcessSkeleton::StrToInt32(realPidStr, callerRealPidTmp)) {
ZLOGE(LABEL, "get callerRealPid fail, realPidStr:%{public}s", realPidStr.c_str());
return false;
}
if (callerRealPidTmp < 0) {
ZLOGE(LABEL, "illegal callerRealPid:%{public}d", callerRealPidTmp);
return false;
}
callerRealPid = static_cast<pid_t>(callerRealPidTmp);
return true;
}
bool BinderInvoker::GetCallerPidAndUidByStr(const std::string &str, size_t offset, pid_t &pid, pid_t &uid)
{
if (str.length() <= offset) {
ZLOGE(LABEL, "illegal offset, len:%{public}zu, offset:%{public}zu", str.length(), offset);
return false;
}
uint64_t pidUid = 0;
if (!GetUint64ValueByStrSlice(str, offset, str.length() - offset, pidUid)) {
ZLOGE(LABEL, "get pidUid fail");
return false;
}
pid_t pidTmp = static_cast<pid_t>(pidUid);
pid_t uidTmp = static_cast<pid_t>(pidUid >> PID_LEN);
if (pidTmp < 0 || uidTmp < 0) {
ZLOGE(LABEL, "illegal pid and uid, pid:%{public}d, tid:%{public}d", pidTmp, uidTmp);
return false;
}
pid = pidTmp;
uid = uidTmp;
return true;
}
#ifdef CONFIG_IPC_SINGLE
} // namespace IPC_SINGLE
#endif

View File

@ -958,8 +958,9 @@ bool DBinderDatabusInvoker::SetCallingIdentity(std::string &identity, bool flag)
return false;
}
std::string tokenIdStr;
uint64_t tokenId = 0;
if (!ProcessSkeleton::GetSubStr(identity, tokenIdStr, 0, ACCESS_TOKEN_MAX_LEN) ||
!ProcessSkeleton::IsNumStr(tokenIdStr)) {
!ProcessSkeleton::StrToUint64(tokenIdStr, tokenId)) {
ZLOGE(LOG_LABEL, "Identity param tokenId is invalid");
return false;
}
@ -975,17 +976,16 @@ bool DBinderDatabusInvoker::SetCallingIdentity(std::string &identity, bool flag)
return false;
}
size_t subLen = identity.length() - offset;
if (!ProcessSkeleton::GetSubStr(identity, tokenStr, offset, subLen) || !ProcessSkeleton::IsNumStr(tokenStr)) {
uint64_t token = 0;
if (!ProcessSkeleton::GetSubStr(identity, tokenStr, offset, subLen) ||
!ProcessSkeleton::StrToUint64(tokenStr, token)) {
ZLOGE(LOG_LABEL, "Identity param token is invalid");
return false;
}
uint64_t tokenId = std::stoull(tokenIdStr.c_str());
uint64_t token = std::stoull(tokenStr.c_str());
callerUid_ = static_cast<int>(token >> PID_LEN);
callerPid_ = static_cast<int>(token);
callerUid_ = static_cast<pid_t>(token >> PID_LEN);
callerPid_ = static_cast<pid_t>(token);
callerDeviceID_ = deviceId;
callerTokenID_ = tokenId;
return true;
}

View File

@ -78,6 +78,37 @@ HWTEST_F(BinderInvokerUnitTest, SetCallingIdentityTest002, TestSize.Level1)
EXPECT_TRUE(ret);
}
/**
* @tc.name: SetCallingIdentityTest003
* @tc.desc: Override SetCallingIdentity branch
* @tc.type: FUNC
*/
HWTEST_F(BinderInvokerUnitTest, SetCallingIdentityTest003, TestSize.Level1)
{
std::string testCallerSid = "test";
uint64_t testCallerTokenID = 1;
pid_t testCallerRealPid = 1;
pid_t testCallerPid = getpid();
pid_t testCallerUid = getuid();
std::stringstream ss;
ss << testCallerSid << "<";
ss << std::setw(BinderInvoker::ACCESS_TOKEN_MAX_LEN) << std::setfill('0') << testCallerTokenID;
ss << std::setw(BinderInvoker::ACCESS_TOKEN_MAX_LEN) << std::setfill('0') << testCallerRealPid;
ss << std::to_string((static_cast<uint64_t>(testCallerUid) << PID_LEN) | static_cast<uint64_t>(testCallerPid));
std::string identity = ss.str();
std::cout << "identity=" << identity << std::endl;
BinderInvoker binderInvoker;
bool ret = binderInvoker.SetCallingIdentity(identity, false);
EXPECT_TRUE(ret);
EXPECT_EQ(binderInvoker.callerSid_, testCallerSid);
EXPECT_EQ(binderInvoker.callerTokenID_, testCallerTokenID);
EXPECT_EQ(binderInvoker.callerPid_, testCallerPid);
EXPECT_EQ(binderInvoker.callerUid_, testCallerUid);
}
/**
* @tc.name: ReadFileDescriptor001
* @tc.desc: Verify the ReadFileDescriptor function

View File

@ -41,6 +41,7 @@ const std::string DEVICE_ID_TEST = "deviceidTest";
const std::string SESSION_NAME_TEST = "sessionNameTest";
const std::string PEER_SESSION_NAME_TEST = "peerSessionNameTest";
const std::string SERVICE_NAME_TEST = "serviceNameTest";
const uint32_t DEVICEID_LENGTH_TEST = 64;
}
class IPCDbinderDataBusInvokerTest : public testing::Test {
@ -774,7 +775,6 @@ HWTEST_F(IPCDbinderDataBusInvokerTest, ResetCallingIdentityTest001, TestSize.Lev
*/
HWTEST_F(IPCDbinderDataBusInvokerTest, SetCallingIdentityTest001, TestSize.Level1)
{
#define DEVICEID_LENGTH_TEST 64
uint64_t tokenId = 1;
uint64_t pid = 1;
char buf[ACCESS_TOKEN_MAX_LEN + 1] = {0};
@ -794,6 +794,35 @@ HWTEST_F(IPCDbinderDataBusInvokerTest, SetCallingIdentityTest001, TestSize.Level
EXPECT_TRUE(result);
}
/**
* @tc.name: SetCallingIdentityTest002
* @tc.desc: SetCallingIdentity
* @tc.type: FUNC
*/
HWTEST_F(IPCDbinderDataBusInvokerTest, SetCallingIdentityTest002, TestSize.Level1)
{
uint64_t testCallerTokenID = 1;
std::string testCallerDeviceID(DEVICEID_LENGTH_TEST, 'a');
pid_t testCallerPid = getpid();
pid_t testCallerUid = getuid();
std::stringstream ss;
ss << std::setw(DBinderDatabusInvoker::ACCESS_TOKEN_MAX_LEN) << std::setfill('0') << testCallerTokenID;
ss << testCallerDeviceID;
ss << std::to_string((static_cast<uint64_t>(testCallerUid) << PID_LEN) | static_cast<uint64_t>(testCallerPid));
std::string identity = ss.str();
std::cout << "identity=" << identity << std::endl;
DBinderDatabusInvoker testInvoker;
bool result = testInvoker.SetCallingIdentity(identity, false);
EXPECT_TRUE(result);
EXPECT_EQ(testInvoker.callerTokenID_, testCallerTokenID);
EXPECT_EQ(testInvoker.callerDeviceID_, testCallerDeviceID);
EXPECT_EQ(testInvoker.callerPid_, testCallerPid);
EXPECT_EQ(testInvoker.callerUid_, testCallerUid);
}
/**
* @tc.name: TranslateIRemoteObjectTest001
* @tc.desc: TranslateIRemoteObject

View File

@ -222,4 +222,121 @@ HWTEST_F(ProcessSkeletonUnitTest, IsPrintTest001, TestSize.Level1)
EXPECT_EQ(isPrint, true);
EXPECT_EQ(lastErr, 1);
EXPECT_EQ(lastErrCnt, 0);
}
/**
* @tc.name: StrToUint64001
* @tc.desc: Verify the IsPrint function
* @tc.type: FUNC
*/
HWTEST_F(ProcessSkeletonUnitTest, StrToUint64001, TestSize.Level1)
{
uint64_t value = 0;
bool ret = false;
ret = ProcessSkeleton::StrToUint64("", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("0", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 0);
ret = ProcessSkeleton::StrToUint64("1", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 1);
std::string uint64MaxVal = std::to_string(UINT64_MAX);
ret = ProcessSkeleton::StrToUint64(uint64MaxVal, value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, UINT64_MAX);
// UINT64_MAX + 1
ret = ProcessSkeleton::StrToUint64("18446744073709551616", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("-0", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 0);
ret = ProcessSkeleton::StrToUint64("-1", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, UINT64_MAX);
ret = ProcessSkeleton::StrToUint64("- 1", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("a1", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("1a", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("99999999999999999999", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToUint64("3.14", value);
EXPECT_FALSE(ret);
}
/**
* @tc.name: StrToInt32001
* @tc.desc: Verify the IsPrint function
* @tc.type: FUNC
*/
HWTEST_F(ProcessSkeletonUnitTest, StrToInt32001, TestSize.Level1)
{
int32_t value = 0;
bool ret = false;
ret = ProcessSkeleton::StrToInt32("", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("0", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 0);
ret = ProcessSkeleton::StrToInt32("1", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 1);
std::string int32MaxVal = std::to_string(INT32_MAX);
ret = ProcessSkeleton::StrToInt32(int32MaxVal, value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, INT32_MAX);
// INT32_MAX + 1
ret = ProcessSkeleton::StrToInt32("2147483648", value);
EXPECT_FALSE(ret);
std::string int32MinVal = std::to_string(INT32_MIN);
ret = ProcessSkeleton::StrToInt32(int32MinVal, value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, INT32_MIN);
// INT32_MIN - 1
ret = ProcessSkeleton::StrToInt32("-2147483649", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("-0", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, 0);
ret = ProcessSkeleton::StrToInt32("-1", value);
EXPECT_TRUE(ret);
EXPECT_EQ(value, -1);
ret = ProcessSkeleton::StrToInt32("- 1", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("a1", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("1a", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("99999999999999999999", value);
EXPECT_FALSE(ret);
ret = ProcessSkeleton::StrToInt32("3.14", value);
EXPECT_FALSE(ret);
}