rsrv: cross-check m_count message field with payload buffer length

Bounds check m_count / element count against dbChannel.

For write_notify_action only.
Bounds check DBR data size against received payload buffer length

For write_action, add pre-test with dbr_size_n() before caNetConvert()
This commit is contained in:
Michael Davidsaver authored and Dirk Zimoch committed 2026-10-14 15:12:08 +02:00
1 parent b2fde23f53
commit d06647836f
1 file changed
+34 -3
+34 -3
View File
@@ -675,6 +675,9 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
SEND_UNLOCK ( pClient );
return RSRV_ERROR;
}
if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
mp->m_count = dbChannelFinalElements(pciu->dbch);
}
payloadSize = dbr_size_n ( mp->m_dataType, mp->m_count );
status = cas_copy_in_header ( pClient, mp->m_cmmd, payloadSize,
@@ -759,6 +762,10 @@ static int read_notify_action ( caHdrLargeArray *mp, void *pPayload, struct clie
return RSRV_ERROR;
}
if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
mp->m_count = dbChannelFinalElements(pciu->dbch);
}
evext.msg = *mp;
evext.pciu = pciu;
evext.pdbev = NULL;
@@ -788,6 +795,7 @@ static int write_action ( caHdrLargeArray *mp,
int status;
long dbStatus;
void *asWritePvt;
unsigned size;
pciu = MPTOPCIU(mp, client);
if(!pciu){
@@ -795,6 +803,19 @@ static int write_action ( caHdrLargeArray *mp,
return RSRV_ERROR;
}
if (INVALID_DB_REQ(mp->m_dataType)) {
log_header ("bad put data type", client, mp, pPayload, 0);
return RSRV_ERROR;
}
if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
mp->m_count = dbChannelFinalElements(pciu->dbch);
}
size = dbr_size_n (mp->m_dataType, mp->m_count);
if (size > mp->m_postsize) {
return RSRV_ERROR;
}
if(!rsrvCheckPut(pciu)){
status = ECA_NOWTACCESS;
SEND_LOCK(client);
@@ -1702,11 +1723,14 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
return RSRV_ERROR;
}
if (mp->m_dataType > LAST_BUFFER_TYPE) {
if (INVALID_DB_REQ(mp->m_dataType)) {
log_header ("bad put notify data type", client, mp, pPayload, 0);
putNotifyErrorReply (client, mp, ECA_BADTYPE);
return RSRV_ERROR;
}
if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
mp->m_count = dbChannelFinalElements(pciu->dbch);
}
if(!rsrvCheckPut(pciu)){
putNotifyErrorReply (client, mp, ECA_NOWTACCESS);
@@ -1714,6 +1738,9 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
}
size = dbr_size_n (mp->m_dataType, mp->m_count);
if (size > mp->m_postsize) {
return RSRV_ERROR;
}
if ( pciu->pPutNotify ) {
@@ -1824,7 +1851,7 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client
struct channel_in_use *pciu;
struct event_ext *pevext;
if ( INVALID_DB_REQ(mp->m_dataType) ) {
if ( INVALID_DB_REQ(mp->m_dataType) || mp->m_postsize < sizeof(*pmi) ) {
return RSRV_ERROR;
}
@@ -1858,6 +1885,10 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client
return RSRV_ERROR;
}
if (mp->m_count > dbChannelFinalElements(pciu->dbch)) {
mp->m_count = dbChannelFinalElements(pciu->dbch);
}
pevext->msg = *mp;
pevext->pciu = pciu;
pevext->size = dbr_size_n(mp->m_dataType, mp->m_count);
@@ -2481,7 +2512,7 @@ int camessage ( struct client *client )
}
msg.m_postsize = ntohl ( pLW[0] );
msg.m_count = ntohl ( pLW[1] );
if (msg.m_postsize >= 0xffffffff - (sizeof(*mp) + 2 * sizeof ( *pLW ))) {
if (msg.m_postsize >= ca_uint32_max - (sizeof(*mp) + 2 * sizeof ( *pLW ))) {
if(CASDEBUG>0) {
errlogPrintf("Client ext msg size too large 0x%08x\n",
(unsigned)msg.m_postsize);