Skip to content

Commit 5b0d45b

Browse files
Add CBMC proof for DHCPProcess IPv4 (#918)
* renaming DHCPProcess to DHCPProcessEndPoint * adding CBMC proof for DHCP process v4 * fix DHCP issues * fix issues and improve coverage * fix formatting * removing unsused code * removing copyright from *.json files * adding changes as per revieew comments
1 parent a9beafa commit 5b0d45b

File tree

7 files changed

+294
-72
lines changed

7 files changed

+294
-72
lines changed

source/FreeRTOS_DHCP.c

100755100644
+2-2
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@
222222
/* No need to initialise 'pucUDPPayload', it just looks nicer. */
223223
uint8_t * pucUDPPayload = NULL;
224224
const DHCPMessage_IPv4_t * pxDHCPMessage;
225-
BaseType_t lBytes;
225+
int32_t lBytes;
226226

227227
while( xDHCPv4Socket != NULL )
228228
{
@@ -232,7 +232,7 @@
232232
/* Peek the next UDP message. */
233233
lBytes = FreeRTOS_recvfrom( xDHCPv4Socket, &( pucUDPPayload ), 0, xRecvFlags, NULL, NULL );
234234

235-
if( lBytes <= 0 )
235+
if( lBytes < ( ( int32_t ) sizeof( DHCPMessage_IPv4_t ) ) )
236236
{
237237
if( ( lBytes < 0 ) && ( lBytes != -pdFREERTOS_ERRNO_EAGAIN ) )
238238
{

test/cbmc/proofs/DHCP/DHCPProcess/DHCPProcess_harness.c

+56-38
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,24 @@ extern DHCPData_t xDHCPData;
5151
extern Socket_t xDHCPv4Socket;
5252
void prvCreateDHCPSocket( NetworkEndPoint_t * pxEndPoint );
5353

54-
/* Static member defined in freertos_api.c */
55-
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
56-
extern uint32_t GetNetworkBuffer_failure_count;
57-
#endif
54+
uint32_t uxSocketCloseCnt = 0;
5855

56+
DHCPMessage_IPv4_t xDHCPMessage;
5957

6058

59+
void __CPROVER_file_local_FreeRTOS_DHCP_c_prvCloseDHCPSocket( const NetworkEndPoint_t * pxEndPoint );
60+
6161
/****************************************************************
62-
* The signature of the function under test.
62+
* vDHCPProcessEndPoint() is proved separately
6363
****************************************************************/
6464

6565
void __CPROVER_file_local_FreeRTOS_DHCP_c_vDHCPProcessEndPoint( BaseType_t xReset,
6666
BaseType_t xDoCheck,
67-
NetworkEndPoint_t * pxEndPoint );
67+
NetworkEndPoint_t * pxEndPoint )
68+
{
69+
__CPROVER_assert( pxEndPoint != NULL,
70+
"FreeRTOS precondition: pxEndPoint != NULL" );
71+
}
6872

6973
/****************************************************************
7074
* Abstract prvProcessDHCPReplies proved memory safe in ProcessDHCPReplies.
@@ -111,25 +115,55 @@ BaseType_t vSocketBind( FreeRTOS_Socket_t * pxSocket,
111115
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
112116
TickType_t xBlockTimeTicks )
113117
{
114-
NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) malloc( sizeof( NetworkBufferDescriptor_t ) );
118+
NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) safeMalloc( sizeof( NetworkBufferDescriptor_t ) );
115119

116120
__CPROVER_assume( pxNetworkBuffer != NULL );
117121
__CPROVER_assume( xRequestedSizeBytes > ( dhcpFIRST_OPTION_BYTE_OFFSET + sizeof( MACAddress_t ) + ipIP_TYPE_OFFSET ) );
118122

119-
pxNetworkBuffer->pucEthernetBuffer = ( ( uint8_t * ) malloc( xRequestedSizeBytes + ( ipIP_TYPE_OFFSET ) ) ) + ipIP_TYPE_OFFSET;
123+
pxNetworkBuffer->pucEthernetBuffer = ( ( uint8_t * ) safeMalloc( xRequestedSizeBytes + ( ipIP_TYPE_OFFSET ) ) );
120124
__CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL );
121125

126+
/* Increment with expected buffer padding */
127+
pxNetworkBuffer->pucEthernetBuffer += ipIP_TYPE_OFFSET;
128+
122129
pxNetworkBuffer->xDataLength = xRequestedSizeBytes;
123130
return pxNetworkBuffer;
124131
}
125132

133+
/* FreeRTOS_ReleaseUDPPayloadBuffer is mocked here and the memory
134+
* is not freed as the buffer allocated by the FreeRTOS_recvfrom is static
135+
* memory */
126136
void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
127137
{
128138
__CPROVER_assert( pvBuffer != NULL,
129139
"FreeRTOS precondition: pvBuffer != NULL" );
140+
}
130141

131-
/* Free buffer after adjusting offsets. */
132-
free( ( ( ( uint8_t * ) pvBuffer ) - ( ipUDP_PAYLOAD_OFFSET_IPv4 + ipIP_TYPE_OFFSET ) ) );
142+
/* For the DHCP process loop to be fully covered, we expect FreeRTOS_recvfrom
143+
* to fail after few iterations. This is because vDHCPProcessEndPoint is proved
144+
* separately and is stubbed out for this proof, which ideally is supposed to close
145+
* the socket and end the loop. */
146+
int32_t FreeRTOS_recvfrom( Socket_t xSocket,
147+
void * pvBuffer,
148+
size_t uxBufferLength,
149+
BaseType_t xFlags,
150+
struct freertos_sockaddr * pxSourceAddress,
151+
socklen_t * pxSourceAddressLength )
152+
153+
{
154+
static uint32_t recvRespCnt = 0;
155+
int32_t retVal = -1;
156+
157+
__CPROVER_assert( pvBuffer != NULL,
158+
"FreeRTOS precondition: pvBuffer != NULL" );
159+
160+
if( ++recvRespCnt < ( FR_RECV_FROM_SUCCESS_COUNT - 1 ) )
161+
{
162+
*( ( void ** ) pvBuffer ) = ( void * ) &xDHCPMessage;
163+
retVal = sizeof( xDHCPMessage );
164+
}
165+
166+
return retVal;
133167
}
134168

135169
/****************************************************************
@@ -139,18 +173,18 @@ void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
139173
void harness()
140174
{
141175
BaseType_t xReset;
142-
BaseType_t xDoCheck;
176+
eDHCPState_t eExpectedState;
143177

144-
pxNetworkEndPoints = ( NetworkEndPoint_t * ) malloc( sizeof( NetworkEndPoint_t ) );
178+
pxNetworkEndPoints = ( NetworkEndPoint_t * ) safeMalloc( sizeof( NetworkEndPoint_t ) );
145179
__CPROVER_assume( pxNetworkEndPoints != NULL );
146180

147181
/* Interface init. */
148-
pxNetworkEndPoints->pxNetworkInterface = ( NetworkInterface_t * ) malloc( sizeof( NetworkInterface_t ) );
182+
pxNetworkEndPoints->pxNetworkInterface = ( NetworkInterface_t * ) safeMalloc( sizeof( NetworkInterface_t ) );
149183
__CPROVER_assume( pxNetworkEndPoints->pxNetworkInterface != NULL );
150184

151185
if( nondet_bool() )
152186
{
153-
pxNetworkEndPoints->pxNext = ( NetworkEndPoint_t * ) malloc( sizeof( NetworkEndPoint_t ) );
187+
pxNetworkEndPoints->pxNext = ( NetworkEndPoint_t * ) safeMalloc( sizeof( NetworkEndPoint_t ) );
154188
__CPROVER_assume( pxNetworkEndPoints->pxNext != NULL );
155189
pxNetworkEndPoints->pxNext->pxNext = NULL;
156190
pxNetworkEndPoints->pxNext->pxNetworkInterface = pxNetworkEndPoints->pxNetworkInterface;
@@ -160,33 +194,17 @@ void harness()
160194
pxNetworkEndPoints->pxNext = NULL;
161195
}
162196

163-
NetworkEndPoint_t * pxNetworkEndPoint_Temp = ( NetworkEndPoint_t * ) malloc( sizeof( NetworkEndPoint_t ) );
164-
__CPROVER_assume( pxNetworkEndPoint_Temp != NULL );
165-
pxNetworkEndPoint_Temp->pxNext = NULL;
166-
167-
/****************************************************************
168-
* Initialize the counter used to bound the number of times
169-
* GetNetworkBufferWithDescriptor can fail.
170-
****************************************************************/
171-
172-
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
173-
GetNetworkBuffer_failure_count = 0;
174-
#endif
175-
176-
/****************************************************************
177-
* Assume a valid socket in most states of the DHCP state machine.
178-
*
179-
* The socket is created in the eWaitingSendFirstDiscover state.
180-
* xReset==True resets the state to eWaitingSendFirstDiscover.
181-
****************************************************************/
182-
183-
if( !( ( pxNetworkEndPoint_Temp->xDHCPData.eDHCPState == eInitialWait ) ||
197+
if( !( ( pxNetworkEndPoints->xDHCPData.eDHCPState == eInitialWait ) ||
184198
( xReset != pdFALSE ) ) )
185199
{
186-
prvCreateDHCPSocket( pxNetworkEndPoint_Temp );
200+
prvCreateDHCPSocket( pxNetworkEndPoints );
187201
}
188202

189-
xDHCPv4Socket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
203+
/* Assume vDHCPProcess is only called on IPv4 endpoints which is
204+
* validated before the call to vDHCPProcess */
205+
__CPROVER_assume( pxNetworkEndPoints->bits.bIPv6 == 0 );
206+
207+
vDHCPProcess( xReset, pxNetworkEndPoints );
190208

191-
__CPROVER_file_local_FreeRTOS_DHCP_c_vDHCPProcessEndPoint( xReset, xDoCheck, pxNetworkEndPoint_Temp );
209+
__CPROVER_file_local_FreeRTOS_DHCP_c_prvCloseDHCPSocket( pxNetworkEndPoints );
192210
}

test/cbmc/proofs/DHCP/DHCPProcess/Makefile.json

+3-31
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,3 @@
1-
#
2-
# FreeRTOS memory safety proofs with CBMC.
3-
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4-
#
5-
# Permission is hereby granted, free of charge, to any person
6-
# obtaining a copy of this software and associated documentation
7-
# files (the "Software"), to deal in the Software without
8-
# restriction, including without limitation the rights to use, copy,
9-
# modify, merge, publish, distribute, sublicense, and/or sell copies
10-
# of the Software, and to permit persons to whom the Software is
11-
# furnished to do so, subject to the following conditions:
12-
#
13-
# The above copyright notice and this permission notice shall be
14-
# included in all copies or substantial portions of the Software.
15-
#
16-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20-
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21-
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23-
# SOFTWARE.
24-
#
25-
# http://aws.amazon.com/freertos
26-
# http://www.FreeRTOS.org
27-
#
28-
291
{
302
"ENTRY": "DHCPProcess",
313

@@ -36,10 +8,10 @@
368
# The number of times GetNetworkBufferWithDescriptor can be allowed to fail
379
# (plus 1).
3810
"FAILURE_BOUND": 2,
11+
"LOOP_UNWIND_COUNT": 4,
3912

4013
"CBMCFLAGS": [
41-
"--unwind 4",
42-
"--unwindset strlen.0:11,memcmp.0:7",
14+
"--unwind {LOOP_UNWIND_COUNT}",
4315
"--nondet-static --flush"
4416
],
4517
"OPT":
@@ -50,13 +22,13 @@
5022
[
5123
"$(ENTRY)_harness.goto",
5224
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
53-
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
5425
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto",
5526
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
5627
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
5728
],
5829
"DEF":
5930
[
31+
"FR_RECV_FROM_SUCCESS_COUNT={LOOP_UNWIND_COUNT}",
6032
"BUFFER_SIZE={BUFFER_SIZE}",
6133
"ipconfigDHCP_REGISTER_HOSTNAME=1",
6234
"CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL=1",

0 commit comments

Comments
 (0)