IPC status fields will be protected by an Adler-32 checksum too.

This commit is contained in:
LoRd_MuldeR 2014-12-14 20:52:58 +01:00
parent 4385a2dfd9
commit bf8ce486d5

View File

@ -50,6 +50,21 @@ namespace MUtils
static const size_t HDR_LEN = 40; static const size_t HDR_LEN = 40;
static const size_t IPC_SLOTS = 128; static const size_t IPC_SLOTS = 128;
typedef struct
{
quint64 counter;
quint32 pos_wr;
quint32 pos_rd;
}
ipc_status_data_t;
typedef struct
{
ipc_status_data_t payload;
quint32 checksum;
}
ipc_status_t;
typedef struct typedef struct
{ {
quint32 command_id; quint32 command_id;
@ -57,11 +72,11 @@ namespace MUtils
char param[MUtils::IPCChannel::MAX_MESSAGE_LEN]; char param[MUtils::IPCChannel::MAX_MESSAGE_LEN];
quint64 timestamp; quint64 timestamp;
} }
ipc_data_t; ipc_msg_data_t;
typedef struct typedef struct
{ {
ipc_data_t payload; ipc_msg_data_t payload;
quint32 checksum; quint32 checksum;
} }
ipc_msg_t; ipc_msg_t;
@ -69,9 +84,7 @@ namespace MUtils
typedef struct typedef struct
{ {
char header[HDR_LEN]; char header[HDR_LEN];
quint64 counter; ipc_status_t status;
quint32 pos_wr;
quint32 pos_rd;
ipc_msg_t data[IPC_SLOTS]; ipc_msg_t data[IPC_SLOTS];
} }
ipc_t; ipc_t;
@ -130,8 +143,11 @@ MUtils::IPCChannel::IPCChannel(const QString &applicationId, const quint32 &appV
m_appVersionNo(appVersionNo), m_appVersionNo(appVersionNo),
m_headerStr(QCryptographicHash::hash(MAKE_ID(applicationId, appVersionNo, channelId, "header").toLatin1(), QCryptographicHash::Sha1).toHex()) m_headerStr(QCryptographicHash::hash(MAKE_ID(applicationId, appVersionNo, channelId, "header").toLatin1(), QCryptographicHash::Sha1).toHex())
{ {
assert(m_headerStr.length() == HDR_LEN);
p->initialized = false; p->initialized = false;
if(m_headerStr.length() != Internal::HDR_LEN)
{
MUTILS_THROW("Invalid header length has been detected!");
}
} }
MUtils::IPCChannel::~IPCChannel(void) MUtils::IPCChannel::~IPCChannel(void)
@ -235,6 +251,7 @@ int MUtils::IPCChannel::initialize(void)
{ {
memset(ptr, 0, sizeof(Internal::ipc_t)); memset(ptr, 0, sizeof(Internal::ipc_t));
memcpy(&ptr->header[0], m_headerStr.constData(), Internal::HDR_LEN); memcpy(&ptr->header[0], m_headerStr.constData(), Internal::HDR_LEN);
ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
} }
else else
{ {
@ -287,6 +304,9 @@ bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, cons
} }
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data())) if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{
const quint32 status_checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
if(status_checksum == ptr->status.checksum)
{ {
Internal::ipc_msg_t ipc_msg; Internal::ipc_msg_t ipc_msg;
memset(&ipc_msg, 0, sizeof(Internal::ipc_msg_t)); memset(&ipc_msg, 0, sizeof(Internal::ipc_msg_t));
@ -297,14 +317,21 @@ bool MUtils::IPCChannel::send(const quint32 &command, const quint32 &flags, cons
{ {
strncpy_s(ipc_msg.payload.param, MAX_MESSAGE_LEN, message, _TRUNCATE); strncpy_s(ipc_msg.payload.param, MAX_MESSAGE_LEN, message, _TRUNCATE);
} }
ipc_msg.payload.timestamp = ptr->counter++; ipc_msg.payload.timestamp = ptr->status.payload.counter++;
ipc_msg.checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_data_t)); ipc_msg.checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_msg_data_t));
memcpy(&ptr->data[ptr->status.payload.pos_wr], &ipc_msg, sizeof(Internal::ipc_msg_t));
ptr->status.payload.pos_wr = (ptr->status.payload.pos_wr + 1) % Internal::IPC_SLOTS;
ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
memcpy(&ptr->data[ptr->pos_wr], &ipc_msg, sizeof(Internal::ipc_msg_t));
ptr->pos_wr = (ptr->pos_wr + 1) % Internal::IPC_SLOTS;
success = true; success = true;
} }
else else
{
qWarning("Corrupted IPC status detected -> skipping!");
}
}
else
{ {
qWarning("Shared memory pointer is NULL -> unable to write data!"); qWarning("Shared memory pointer is NULL -> unable to write data!");
} }
@ -363,25 +390,34 @@ bool MUtils::IPCChannel::read(quint32 &command, quint32 &flags, char *const mess
if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data())) if(Internal::ipc_t *const ptr = reinterpret_cast<Internal::ipc_t*>(p->sharedmem->data()))
{ {
success = true; const quint32 status_checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
memcpy(&ipc_msg, &ptr->data[ptr->pos_rd], sizeof(Internal::ipc_msg_t)); if(status_checksum == ptr->status.checksum)
ptr->pos_rd = (ptr->pos_rd + 1) % Internal::IPC_SLOTS; {
memcpy(&ipc_msg, &ptr->data[ptr->status.payload.pos_rd], sizeof(Internal::ipc_msg_t));
ptr->status.payload.pos_rd = (ptr->status.payload.pos_rd + 1) % Internal::IPC_SLOTS;
ptr->status.checksum = Internal::adler32(ADLER_SEED, &ptr->status.payload, sizeof(Internal::ipc_status_data_t));
const quint32 expected_checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_data_t)); const quint32 msg_checksum = Internal::adler32(ADLER_SEED, &ipc_msg.payload, sizeof(Internal::ipc_msg_data_t));
if((expected_checksum == ipc_msg.checksum) || (ipc_msg.payload.timestamp < ptr->counter)) if((msg_checksum == ipc_msg.checksum) || (ipc_msg.payload.timestamp < ptr->status.payload.counter))
{ {
command = ipc_msg.payload.command_id; command = ipc_msg.payload.command_id;
flags = ipc_msg.payload.flags; flags = ipc_msg.payload.flags;
strncpy_s(message, buffSize, ipc_msg.payload.param, _TRUNCATE); strncpy_s(message, buffSize, ipc_msg.payload.param, _TRUNCATE);
success = true;
} }
else else
{ {
qWarning("Malformed or corrupted IPC message, will be ignored"); qWarning("Malformed or corrupted IPC message, will be ignored!");
} }
} }
else else
{ {
qWarning("Shared memory pointer is NULL -> unable to write data!"); qWarning("Corrupted IPC status detected -> skipping!");
}
}
else
{
qWarning("Shared memory pointer is NULL -> unable to read data!");
} }
if(!p->sharedmem->unlock()) if(!p->sharedmem->unlock())