LocIpc could be using data member from a deleted obj

startListeningBlocking is meant to be called under a reader
thread, which is the case if startListeningNonBlocking calls
it. A LocIpc client may delete the LocIpc obj, which would
trigger sending an ABORT msg to the reader thread before it
is subsequently deleted, in which case, it is possible that
when the reader thread comes around to process the ABORT msg,
referencing the data members of the possibly stale obj would
cause unpredictable behaviors.

Change-Id: I441af85c04d92b6fff695c020e3e0b4bd5e90409
CRs-Fixed: 2380093
This commit is contained in:
Kevin Tang 2019-01-11 17:41:30 -08:00 committed by Gerrit - the friendly Code Review server
parent 400c1e8b57
commit 99e5e01b13
2 changed files with 53 additions and 67 deletions

View file

@ -69,8 +69,9 @@ bool LocIpc::startListeningNonBlocking(const std::string& name) {
}
bool LocIpc::startListeningBlocking(const std::string& name) {
bool stopRequested = false;
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
LOC_LOGe("create socket error. reason:%s", strerror(errno));
return false;
@ -87,89 +88,75 @@ bool LocIpc::startListeningBlocking(const std::string& name) {
if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
LOC_LOGe("bind socket error. reason:%s", strerror(errno));
::close(fd);
fd = -1;
return false;
}
} else {
mIpcFd = fd;
mIpcFd = fd;
// inform that the socket is ready to receive message
onListenerReady();
// inform that the socket is ready to receive message
onListenerReady();
ssize_t nBytes = 0;
std::string msg = "";
std::string abort = LOC_MSG_ABORT;
while (1) {
msg.resize(LOC_MSG_BUF_LEN);
nBytes = ::recvfrom(mIpcFd, (void*)(msg.data()), msg.size(), 0, NULL, NULL);
if (nBytes < 0) {
break;
} else if (nBytes == 0) {
continue;
}
if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) {
LOC_LOGi("recvd abort msg.data %s", msg.data());
break;
}
if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) {
// short message
msg.resize(nBytes);
onReceive(msg);
} else {
// long message
size_t msgLen = 0;
sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen);
msg.resize(msgLen);
size_t msgLenReceived = 0;
while ((msgLenReceived < msgLen) && (nBytes > 0)) {
nBytes = recvfrom(mIpcFd, (void*)&(msg[msgLenReceived]),
msg.size() - msgLenReceived, 0, NULL, NULL);
msgLenReceived += nBytes;
ssize_t nBytes = 0;
std::string msg = "";
std::string abort = LOC_MSG_ABORT;
while (1) {
msg.resize(LOC_MSG_BUF_LEN);
nBytes = ::recvfrom(fd, (void*)(msg.data()), msg.size(), 0, NULL, NULL);
if (nBytes < 0) {
LOC_LOGe("cannot read socket. reason:%s", strerror(errno));
break;
} else if (0 == nBytes) {
continue;
}
if (nBytes > 0) {
onReceive(msg);
} else {
if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) {
LOC_LOGi("recvd abort msg.data %s", msg.data());
stopRequested = true;
break;
}
if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) {
// short message
msg.resize(nBytes);
onReceive(msg);
} else {
// long message
size_t msgLen = 0;
sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen);
msg.resize(msgLen);
size_t msgLenReceived = 0;
while ((msgLenReceived < msgLen) && (nBytes > 0)) {
nBytes = recvfrom(fd, (void*)&(msg[msgLenReceived]),
msg.size() - msgLenReceived, 0, NULL, NULL);
msgLenReceived += nBytes;
}
if (nBytes > 0) {
onReceive(msg);
} else {
LOC_LOGe("cannot read socket. reason:%s", strerror(errno));
break;
}
}
}
}
if (mStopRequested) {
mStopRequested = false;
return true;
} else {
LOC_LOGe("cannot read socket. reason:%s", strerror(errno));
(void)::close(mIpcFd);
mIpcFd = -1;
return false;
if (::close(fd)) {
LOC_LOGe("cannot close socket:%s", strerror(errno));
}
unlink(name.c_str());
return stopRequested;
}
void LocIpc::stopListening() {
const char *socketName = nullptr;
mStopRequested = true;
if (mRunnable) {
if (mIpcFd >= 0) {
std::string abort = LOC_MSG_ABORT;
socketName = (reinterpret_cast<LocIpcRunnable *>(mRunnable))->mIpcName.c_str();
send(socketName, abort);
mRunnable = nullptr;
}
if (mIpcFd >= 0) {
if (::close(mIpcFd)) {
LOC_LOGe("cannot close socket:%s", strerror(errno));
}
mIpcFd = -1;
}
//delete from the file system at the end
if (socketName) {
unlink(socketName);
if (mRunnable) {
mRunnable = nullptr;
}
}

View file

@ -44,7 +44,7 @@ class LocIpcSender;
class LocIpc {
friend LocIpcSender;
public:
inline LocIpc() : mIpcFd(-1), mStopRequested(false), mRunnable(nullptr) {}
inline LocIpc() : mIpcFd(-1), mRunnable(nullptr) {}
inline virtual ~LocIpc() { stopListening(); }
// Listen for new messages in current thread. Calling this funciton will
@ -93,7 +93,6 @@ private:
const uint8_t data[], uint32_t length);
int mIpcFd;
bool mStopRequested;
LocThread mThread;
LocRunnable *mRunnable;
};