[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,10 @@
# These files are generated by make_type_header_files.py
*_datastructure.h
Makefile
Makefile.common
cbmc-batch.yaml
**/*.txt
**/*.goto
!CMakeLists.txt

View File

@ -0,0 +1,29 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
/*We assume that the pxGetNetworkBufferWithDescriptor function is implemented correctly and returns a valid data structure. */
/*This is the mock to mimic the correct expected behavior. If this allocation fails, this might invalidate the proof. */
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) malloc( sizeof( NetworkBufferDescriptor_t ) );
__CPROVER_assume( pxNetworkBuffer != NULL );
pxNetworkBuffer->pucEthernetBuffer = malloc( xRequestedSizeBytes );
__CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL );
pxNetworkBuffer->xDataLength = xRequestedSizeBytes;
return pxNetworkBuffer;
}
void harness()
{
vARPAgeCache();
}

View File

@ -0,0 +1,19 @@
{
"ENTRY": "ARPAgeCache",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset vARPAgeCache.0:7",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,2 @@
Assuming that xNetworkInterfaceOutput is memory safe,
this harness proves the memory safety of the vARPAgeCache function.

View File

@ -0,0 +1,32 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
void harness()
{
/*
* The assumption made here is that the buffer pointed by pucEthernetBuffer
* is at least allocated to sizeof(ARPPacket_t) size but eventually a even larger buffer.
* This is not checked inside vARPGenerateRequestPacket.
*/
uint8_t ucBUFFER_SIZE;
__CPROVER_assume( ucBUFFER_SIZE >= sizeof( ARPPacket_t ) && ucBUFFER_SIZE < 2 * sizeof( ARPPacket_t ) );
void * xBuffer = malloc( ucBUFFER_SIZE );
__CPROVER_assume( xBuffer != NULL );
NetworkBufferDescriptor_t xNetworkBuffer2;
xNetworkBuffer2.pucEthernetBuffer = xBuffer;
xNetworkBuffer2.xDataLength = ucBUFFER_SIZE;
/* vARPGenerateRequestPacket asserts buffer has room for a packet */
__CPROVER_assume( xNetworkBuffer2.xDataLength >= sizeof( ARPPacket_t ) );
vARPGenerateRequestPacket( &xNetworkBuffer2 );
}

View File

@ -0,0 +1,16 @@
{
"ENTRY": "ARPGenerateRequestPacket",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,3 @@
Given that the pointer target of xNetworkDescriptor.pucEthernetBuffer is allocated
to the size claimed in xNetworkDescriptor.xDataLength,
this harness proves the memory safety of ARPGenerateRequestPacket.

View File

@ -0,0 +1,17 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
void harness()
{
uint32_t ulIPAddress;
MACAddress_t xMACAddress;
eARPGetCacheEntry( &ulIPAddress, &xMACAddress );
}

View File

@ -0,0 +1,41 @@
{
"ENTRY": "ARPGetCacheEntry",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvCacheLookup.0:7",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
{
"ARPGetCacheEntry_default":[
"ipconfigARP_STORES_REMOTE_ADDRESSES=0",
"ipconfigUSE_LLMNR=0"
]
},
{
"ARPGetCacheEntry_LLMNR": [
"ipconfigARP_STORES_REMOTE_ADDRESSES=0",
"ipconfigUSE_LLMNR=1"
]
},
{
"ARPGetCacheEntry_STORE_REMOTE": [
"ipconfigARP_STORES_REMOTE_ADDRESSES=1",
"ipconfigUSE_LLMNR=0"
]
},
{
"ARPGetCacheEntry_REMOTE_LLMNR": [
"ipconfigARP_STORES_REMOTE_ADDRESSES=1",
"ipconfigUSE_LLMNR=1"
]
}
]
}

View File

@ -0,0 +1,4 @@
The combined proofs in the subdirectories prove that ARPGetCacheEntry
is memory safe for all possible combinations of ipconfigARP_STORES_REMOTE_ADDRESSES
and ipconfigUSE_LLMNR. These are the only configuration
parameters used inside the ARPGetCacheEntry.

View File

@ -0,0 +1,16 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
void harness()
{
MACAddress_t xMACAddress;
uint32_t ulIPAddress;
eARPGetCacheEntryByMac( &xMACAddress, &ulIPAddress );
}

View File

@ -0,0 +1,17 @@
{
"ENTRY": "ARPGetCacheEntryByMac",
"CBMCFLAGS":
[
"--unwind 7",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
"ipconfigUSE_ARP_REVERSED_LOOKUP=1", "ipconfigARP_CACHE_ENTRIES=6"
]
}

View File

@ -0,0 +1,4 @@
ARPGetCacheEntryByMac is memory safe,
if it is enabled.
ARPGetCacheEntryByMac does not use multiple configurations internally.

View File

@ -0,0 +1,51 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
/* This pointer is maintained by the IP-task. Defined in FreeRTOS_IP.c */
extern NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer;
/* This is an output function and need not be tested with this proof. */
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
{
}
void harness()
{
ARPPacket_t xARPFrame;
NetworkBufferDescriptor_t xLocalBuffer;
uint16_t usEthernetBufferSize;
/* Non deterministically determine whether the pxARPWaitingNetworkBuffer will
* point to some valid data or will it be NULL. */
if( nondet_bool() )
{
/* The packet must at least be as big as an IP Packet. The size is not
* checked in the function as the pointer is stored by the IP-task itself
* and therefore it will always be of the required size. */
__CPROVER_assume( usEthernetBufferSize >= sizeof( IPPacket_t ) );
/* Add matching data length to the network buffer descriptor. */
__CPROVER_assume( xLocalBuffer.xDataLength == usEthernetBufferSize );
xLocalBuffer.pucEthernetBuffer = malloc( usEthernetBufferSize );
/* Since this pointer is maintained by the IP-task, either the pointer
* pxARPWaitingNetworkBuffer will be NULL or xLocalBuffer.pucEthernetBuffer
* will be non-NULL. */
__CPROVER_assume( xLocalBuffer.pucEthernetBuffer != NULL );
pxARPWaitingNetworkBuffer = &xLocalBuffer;
}
else
{
pxARPWaitingNetworkBuffer = NULL;
}
eARPProcessPacket( &xARPFrame );
}

View File

@ -0,0 +1,15 @@
{
"ENTRY": "ARPProcessPacket",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset vARPRefreshCacheEntry.0:7,memcmp.0:17,xIsIPInARPCache.0:7",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto"
]
}

View File

@ -0,0 +1,4 @@
The proofs in the subdirectories show that
ARPProcessPacket is memory safe independent
of the configuration value of
ipconfigARP_USE_CLASH_DETECTION.

View File

@ -0,0 +1,16 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_ARP.h"
void harness()
{
MACAddress_t xMACAddress;
uint32_t ulIPAddress;
vARPRefreshCacheEntry( &xMACAddress, ulIPAddress );
vARPRefreshCacheEntry( NULL, ulIPAddress );
}

View File

@ -0,0 +1,19 @@
{
"ENTRY": "ARPRefreshCacheEntry",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset vARPRefreshCacheEntry.0:7,memcmp.0:17",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
{"NOT_STORE_REMOTE":["ipconfigARP_STORES_REMOTE_ADDRESSES=0"]},
{"STORE_REMOTE":["ipconfigARP_STORES_REMOTE_ADDRESSES=1"]}
]
}

View File

@ -0,0 +1,4 @@
The proofs in this directory guarantee together that
ARPRefreshCacheEntry is memory safe independent
of the configuration value of
ipconfigARP_STORES_REMOTE_ADDRESSES.

View File

@ -0,0 +1,13 @@
/* / * FreeRTOS includes. * / */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_ARP.h"
void harness()
{
vARPSendGratuitous();
}

View File

@ -0,0 +1,18 @@
{
"ENTRY": "ARPSendGratuitous",
"CBMCFLAGS":
[
"--unwind 1",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,6 @@
Abstracting xQueueGenericSend away
and including tasks.c and FreeRTOS_IP.c:
The ARPSendGratutious function is memory safe,
if xQueueGenericSend is memory safe.
queue.c is not compiled into the proof binary.

View File

@ -0,0 +1,12 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_ARP.h"
void harness()
{
FreeRTOS_ClearARP();
}

View File

@ -0,0 +1,15 @@
{
"ENTRY": "ClearARP",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,2 @@
This proof demonstrates the memory safety of the ClearARP function in the FreeRTOS_ARP.c file.
No restrictions are made.

View File

@ -0,0 +1,58 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "OutputARPRequest",
"CBMCFLAGS":
[
"--unwind 20"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
#That is the minimal required size for an ARPPacket_t plus offset in the buffer.
"MINIMUM_PACKET_BYTES": 50,
"DEF":
[
{
"CBMC_PROOF_ASSUMPTION_HOLDS_Packet_bytes": [
"CBMC_PROOF_ASSUMPTION_HOLDS=1",
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}"
]
},
{
"CBMC_PROOF_ASSUMPTION_HOLDS_no_packet_bytes": ["CBMC_PROOF_ASSUMPTION_HOLDS=1"]
},
{
"CBMC_PROOF_ASSUMPTION_DOES_NOT_HOLD": ["CBMC_PROOF_ASSUMPTION_HOLDS=0"]
}
]
}

View File

@ -0,0 +1,81 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
ARPPacket_t xARPPacket;
NetworkBufferDescriptor_t xNetworkBuffer;
/* STUB!
* We assume that the pxGetNetworkBufferWithDescriptor function is
* implemented correctly and returns a valid data structure.
* This is the mock to mimic the expected behavior.
* If this allocation fails, this might invalidate the proof.
* FreeRTOS_OutputARPRequest calls pxGetNetworkBufferWithDescriptor
* to get a NetworkBufferDescriptor. Then it calls vARPGenerateRequestPacket
* passing this buffer along in the function call. vARPGenerateRequestPacket
* casts the pointer xNetworkBuffer.pucEthernetBuffer into an ARPPacket_t pointer
* and writes a complete ARPPacket to it. Therefore the buffer has to be at least of the size
* of an ARPPacket to guarantee memory safety.
*/
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
TickType_t xBlockTimeTicks )
{
#ifdef CBMC_PROOF_ASSUMPTION_HOLDS
#if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
xNetworkBuffer.pucEthernetBuffer = malloc( ipconfigETHERNET_MINIMUM_PACKET_BYTES );
#else
xNetworkBuffer.pucEthernetBuffer = malloc( xRequestedSizeBytes );
#endif
#else
uint32_t malloc_size;
__CPROVER_assert( !__CPROVER_overflow_mult( 2, xRequestedSizeBytes ) );
__CPROVER_assume( malloc_size > 0 && malloc_size < 2 * xRequestedSizeBytes );
xNetworkBuffer.pucEthernetBuffer = malloc( malloc_size );
#endif
__CPROVER_assume( xNetworkBuffer.pucEthernetBuffer != NULL );
xNetworkBuffer.xDataLength = xRequestedSizeBytes;
return &xNetworkBuffer;
}
void harness()
{
uint32_t ulIPAddress;
FreeRTOS_OutputARPRequest( ulIPAddress );
}

View File

@ -0,0 +1,29 @@
This is the memory safety proof for FreeRTOS_OutputARPRequest.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* xNetworkInterfaceOutput
This proof checks FreeRTOS_OutputARPRequest in multiple configuration:
* The config_CBMC_PROOF_ASSUMPTION_HOLDS_no_packet_bytes proof
guarantees that for a buffer allocated to xDataLength,
the code executed by the FreeRTOS_OutputARPRequest function
call of FreeRTOS_ARP.c is memory safe.
* If the ipconfigETHERNET_MINIMUM_PACKET_BYTES is set and the
buffer allocated by pxGetNetworkBufferWithDescriptor allocates
a buffer of at least ipconfigETHERNET_MINIMUM_PACKET_BYTES,
the config_CBMC_PROOF_ASSUMPTION_HOLDS_Packet_bytes proof
guarantees that the code executed by the
FreeRTOS_OutputARPRequest function call
of FreeRTOS_ARP.c is memory safe.
* The third configuration in the subdirectory
config_CBMC_PROOF_ASSUMPTION_DOES_NOT_HOLD demonstrates
that the code is not memory safe, if the allocation
code violates our assumption.
* All proofs mock the pxGetNetworkBufferWithDescriptor
function for modelling the assumptions about the
buffer management layer.

View File

@ -0,0 +1,14 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOSIPConfig.h"
#include "FreeRTOS_ARP.h"
void harness()
{
FreeRTOS_PrintARPCache();
}

View File

@ -0,0 +1,17 @@
{
"ENTRY": "FreeRTOS_PrintARPCache",
"CBMCFLAGS":
[
"--unwind 7",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
"ipconfigARP_CACHE_ENTRIES=6"
]
}

View File

@ -0,0 +1,4 @@
FreeRTOS_PrintARPCache_harness.c is memory safe,
assuming vLoggingPrintf is correct and memory safe.
FreeRTOS_PrintARPCache does not use multiple configurations.

View File

@ -0,0 +1,48 @@
{
"ENTRY": "OutputARPRequest",
"MINIMUM_PACKET_BYTES": 50,
"CBMCFLAGS":
[
"--unwind {MINIMUM_PACKET_BYTES}",
"--unwindset xNetworkBuffersInitialise.0:3,xNetworkBuffersInitialise.1:3,vListInsert.0:3,pxGetNetworkBufferWithDescriptor.0:3,pxGetNetworkBufferWithDescriptor.1:3,vNetworkInterfaceAllocateRAMToBuffers.0:3"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_1.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.goto"
],
"DEF":
[
{
"minimal_configuration":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigUSE_LINKED_RX_MESSAGES=0"
]
},
{
"minimal_configuration_minimal_packet_size":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}"
]
},
{
"minimal_configuration_linked_rx_messages":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigUSE_LINKED_RX_MESSAGES=1"
]
}
]
}

View File

@ -0,0 +1,82 @@
/* This harness is linked against
* libraries/freertos_plus/standard/freertos_plus_tcp/source/portable/BufferManagement/BufferAllocation_1.goto
*/
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#if ( ipconfigUSE_LLMNR == 1 )
#include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
for( int x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
NetworkBufferDescriptor_t * current = &pxNetworkBuffers[ x ];
#if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
current->pucEthernetBuffer = malloc( sizeof( ARPPacket_t ) + ( ipconfigETHERNET_MINIMUM_PACKET_BYTES - sizeof( ARPPacket_t ) ) );
#else
current->pucEthernetBuffer = malloc( sizeof( ARPPacket_t ) );
#endif
__CPROVER_assume( current->pucEthernetBuffer != NULL );
current->xDataLength = sizeof( ARPPacket_t );
}
}
/* The code expects that the Semaphore creation relying on pvPortMalloc
* is successful. This is checked by an assert statement, that gets
* triggered when the allocation fails. Nevertheless, the code is perfectly
* guarded against a failing Semaphore allocation. To make the assert pass,
* it is assumed for now, that pvPortMalloc doesn't fail. Using a model allowing
* failures of the allocation might be possible
* after removing the assert in l.105 of BufferAllocation_1.c, from a memory
* safety point of view. */
void * pvPortMalloc( size_t xWantedSize )
{
void * ptr = malloc( xWantedSize );
__CPROVER_assume( ptr != NULL );
return ptr;
}
/*
* This function is implemented by a third party.
* After looking through a couple of samples in the demos folder, it seems
* like the only shared contract is that you want to add the if statement
* for releasing the buffer to the end. Apart from that, it is up to the vendor,
* how to write this code out to the network.
*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
{
if( bReleaseAfterSend != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
}
void harness()
{
BaseType_t xRes = xNetworkBuffersInitialise();
if( xRes == pdPASS )
{
uint32_t ulIPAddress;
FreeRTOS_OutputARPRequest( ulIPAddress );
}
}

View File

@ -0,0 +1,27 @@
This is the memory safety proof for ```FreeRTOS_OutputARPRequest```
method combined with the BufferAllocation_1.c allocation strategy.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* vPortEnterCritical
* vPortExitCritical
* vPortGenerateSimulatedInterrupt
* vAssertCalled
* xTaskGetSchedulerState
* pvTaskIncrementMutexHeldCount
* xTaskRemoveFromEventList
* xTaskPriorityDisinherit
This proof checks ```FreeRTOS_OutputARPRequest``` in multiple configurations.
All assume the memory safety of vNetworkInterfaceAllocateRAMToBuffers.
* The ```config_minimal_configuration``` proof sets
```ipconfigUSE_LINKED_RX_MESSAGES=0```.
* The ```config_minimal_configuration_linked_rx_messages``` proof sets
```ipconfigUSE_LINKED_RX_MESSAGES=1```.
* The ```minimal_configuration_minimal_packet_size``` proof sets
```ipconfigETHERNET_MINIMUM_PACKET_BYTES``` to 50.
All harnesses include the queue.c file, but test only for the happy path.

View File

@ -0,0 +1,49 @@
{
"ENTRY": "OutputARPRequest",
"MINIMUM_PACKET_BYTES": 50,
"CBMCFLAGS":
[
"--unwind {MINIMUM_PACKET_BYTES}",
"--unwindset xNetworkBuffersInitialise.0:3,xNetworkBuffersInitialise.1:3,vListInsert.0:3,pxGetNetworkBufferWithDescriptor.0:3,pxGetNetworkBufferWithDescriptor.1:3,vNetworkInterfaceAllocateRAMToBuffers.0:3"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_2.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.goto"
],
"DEF":
[
{
"minimal_configuration":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigUSE_LINKED_RX_MESSAGES=0"
]
},
{
"minimal_configuration_minimal_packet_size":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}",
"ipconfigUSE_TCP=1"
]
},
{
"minimal_configuration_linked_rx_messages":
[
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
"configUSE_TRACE_FACILITY=0",
"configGENERATE_RUN_TIME_STATS=0",
"ipconfigUSE_LINKED_RX_MESSAGES=1"
]
}
]
}

View File

@ -0,0 +1,62 @@
/* This harness is linked against
* libraries/freertos_plus/standard/freertos_plus_tcp/source/portable/BufferManagement/BufferAllocation_2.goto
*/
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#if ( ipconfigUSE_LLMNR == 1 )
#include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
void * pvPortMalloc( size_t xWantedSize )
{
void * ptr = malloc( xWantedSize );
__CPROVER_assume( ptr != NULL );
return ptr;
}
void vPortFree( void * pv )
{
free( pv );
}
/*
* This function function writes a buffer to the network. We stub it
* out here, and assume it has no side effects relevant to memory safety.
*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
{
if( bReleaseAfterSend != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
}
void harness()
{
BaseType_t xRes = xNetworkBuffersInitialise();
if( xRes == pdPASS )
{
uint32_t ulIPAddress;
FreeRTOS_OutputARPRequest( ulIPAddress );
}
}

View File

@ -0,0 +1,49 @@
This is the memory safety proof for FreeRTOS_OutputARPRequest
method combined with the BufferAllocation_2.c allocation strategy.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* vPortEnterCritical
* vPortExitCritical
* vPortGenerateSimulatedInterrupt
* vAssertCalled
* xTaskGetSchedulerState
* pvTaskIncrementMutexHeldCount
* xTaskRemoveFromEventList
* xTaskPriorityDisinherit
* pvPortMalloc
* pvPortFree
* xNetworkInterfaceOutput
* vNetworkInterfaceAllocateRAMToBuffers
This proof disables the tracing library in the header.
This proof checks FreeRTOS_OutputARPRequest in multiple configuration:
* The proof in the directory config_minimal_configuration guarantees
that the implementation and interaction between
FreeRTOS_OutputARPRequest and
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
are memory save. This proof depends entirely of the implementation
correctness of vNetworkInterfaceAllocateRAMToBuffers.
* The proof in directory minimal_configuration_minimal_packet_size
guarantees that using
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
along with the ipconfigETHERNET_MINIMUM_PACKET_BYTES is memory save
as long as TCP is enabled ( ipconfigUSE_TCP 1 ) and
ipconfigETHERNET_MINIMUM_PACKET_BYTES < sizeof( TCPPacket_t ).
* The directory minimal_configuration_minimal_packet_size_no_tcp
reminds that ipconfigETHERNET_MINIMUM_PACKET_BYTES must not be used
if TCP is disabled ( ipconfigUSE_TCP 1 ) along with the
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
allocator.
* The proof in directory
config_minimal_configuration_linked_rx_messages guarantees that the
ipconfigUSE_LINKED_RX_MESSAGES define does not interfere with the
memory safety claim.
All harnesses include the queue.c file, but test only for the happy path.

View File

@ -0,0 +1,24 @@
{
"ENTRY": "ulARPRemoveCacheEntryByMac",
"NUMBER_OF_CACHE_ENTRIES":6,
"CBMCFLAGS":
[
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"INSTFLAGS":
[
],
"DEF":
[
"ipconfigUSE_ARP_REMOVE_ENTRY=1",
"ipconfigARP_CACHE_ENTRIES={NUMBER_OF_CACHE_ENTRIES}"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
]
}

View File

@ -0,0 +1,20 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_ARP.h"
void harness()
{
const MACAddress_t xMACAddress;
/* The pointer passed to ulARPRemoveCacheEntryByMac cannot be NULL
* (see the API definition). */
ulARPRemoveCacheEntryByMac( &xMACAddress );
}

View File

@ -0,0 +1,52 @@
#include "FreeRTOS.h"
#include "task.h"
#include "tasksStubs.h"
#ifndef TASK_STUB_COUNTER
#define TASK_STUB_COUNTER 0;
#endif
/* 5 is a magic number, but we need some number here as a default value.
* This value is used to bound any loop depending on xTaskCheckForTimeOut
* as a loop bound. It should be overwritten in the Makefile.json adapting
* to the performance requirements of the harness. */
#ifndef TASK_STUB_COUNTER_LIMIT
#define TASK_STUB_COUNTER_LIMIT 5;
#endif
static BaseType_t xCounter = TASK_STUB_COUNTER;
static BaseType_t xCounterLimit = TASK_STUB_COUNTER_LIMIT;
BaseType_t xTaskGetSchedulerState( void )
{
return xState;
}
/* This function is another method apart from overwriting the defines to init the max
* loop bound. */
void vInitTaskCheckForTimeOut( BaseType_t maxCounter,
BaseType_t maxCounter_limit )
{
xCounter = maxCounter;
xCounterLimit = maxCounter_limit;
}
/* This is mostly called in a loop. For CBMC, we have to bound the loop
* to a max limits of calls. Therefore this Stub models a nondet timeout in
* max TASK_STUB_COUNTER_LIMIT iterations.*/
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait )
{
++xCounter;
if( xCounter == xCounterLimit )
{
return pdTRUE;
}
else
{
return nondet_basetype();
}
}

View File

@ -0,0 +1,40 @@
list(APPEND cbmc_compile_options
-m32
)
list(APPEND cbmc_compile_definitions
CBMC
WINVER=0x400
_CONSOLE
_CRT_SECURE_NO_WARNINGS
_DEBUG
_WIN32_WINNT=0x0500
__PRETTY_FUNCTION__=__FUNCTION__
__free_rtos__
)
list(APPEND cbmc_compile_includes
${CMAKE_SOURCE_DIR}/Source/include
${CMAKE_SOURCE_DIR}/Source/portable/MSVC-MingW
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC
${cbmc_dir}/include
${cbmc_dir}/windows
)
# Remove --flag for a specific proof with list(REMOVE_ITEM cbmc_flags --flag)
list(APPEND cbmc_flags
--32
--bounds-check
--pointer-check
--div-by-zero-check
--float-overflow-check
--nan-check
--nondet-static
--pointer-overflow-check
--signed-overflow-check
--undefined-shift-check
--unsigned-overflow-check
)

View File

@ -0,0 +1,103 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h"
#include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
BaseType_t __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions( FreeRTOS_Socket_t * pxSocket,
const NetworkBufferDescriptor_t * pxNetworkBuffer );
/****************************************************************
* Declare the buffer size external to the harness so it can be
* accessed by the preconditions of prvSingleStepTCPHeaderOptions, and
* give the buffer size an unconstrained value in the harness itself.
****************************************************************/
size_t buffer_size;
/****************************************************************
* Function contract proved correct by CheckOptionsOuter
****************************************************************/
int32_t __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag )
{
/* CBMC model of pointers limits the size of the buffer */
/* Preconditions */
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
"prvSingleStepTCPHeaderOptions: buffer_size < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( 8 <= buffer_size,
"prvSingleStepTCPHeaderOptions: 8 <= buffer_size" );
__CPROVER_assert( pucPtr != NULL,
"prvSingleStepTCPHeaderOptions: pucPtr != NULL" );
__CPROVER_assert( uxTotalLength <= buffer_size,
"prvSingleStepTCPHeaderOptions: uxTotalLength <= buffer_size" );
__CPROVER_assert( pxSocket != NULL,
"prvSingleStepTCPHeaderOptions: pxSocket != NULL" );
/* Postconditions */
int32_t index;
__CPROVER_assume( ( index == -1 ) || ( index == 1 ) || ( index <= uxTotalLength ) );
return index;
}
/****************************************************************
* Proof of CheckOptions
****************************************************************/
void harness()
{
/* Give buffer_size an unconstrained value */
size_t buf_size;
buffer_size = buf_size;
/* pxSocket can be any socket */
FreeRTOS_Socket_t pxSocket;
/* pxNetworkBuffer can be any buffer descriptor with any buffer */
NetworkBufferDescriptor_t pxNetworkBuffer;
pxNetworkBuffer.pucEthernetBuffer = malloc( buffer_size );
__CPROVER_assume( pxNetworkBuffer.pucEthernetBuffer != NULL );
pxNetworkBuffer.xDataLength = buffer_size;
/****************************************************************
* Specification and proof of CheckOptions
****************************************************************/
/* CBMC model of pointers limits the size of the buffer */
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
/* Bound required to bound iteration over the buffer */
__CPROVER_assume( buffer_size <= BUFFER_SIZE );
/* Buffer must be big enough to hold pxTCPPacket and pxTCPHeader */
__CPROVER_assume( buffer_size > 47 );
__CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions( &pxSocket, &pxNetworkBuffer );
}

View File

@ -0,0 +1,27 @@
{
"ENTRY": "CheckOptions",
"CBMCFLAGS":
[
"--unwind 1",
" --unwindset __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions.0:41"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
],
"BUFFER_SIZE": 100,
"DEF":
[
"BUFFER_SIZE={BUFFER_SIZE}"
],
"OPT":
[
"--export-file-local-symbols"
]
}

View File

@ -0,0 +1,104 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h"
#include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
void prvReadSackOption( const uint8_t * const pucPtr,
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket );
/****************************************************************
* Proof of prvReadSackOption function contract
****************************************************************/
void harness()
{
/* pucPtr points into a buffer */
size_t buffer_size;
uint8_t * pucPtr = malloc( buffer_size );
__CPROVER_assume( pucPtr != NULL );
/* uxIndex in an index into the buffer */
size_t uxIndex;
/* pxSocket can be any socket with some initialized values */
FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
__CPROVER_assume( pxSocket != NULL );
pxSocket->u.xTCP.txStream = malloc( sizeof( StreamBuffer_t ) );
__CPROVER_assume( pxSocket->u.xTCP.txStream != NULL );
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue );
if( nondet_bool() )
{
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
__CPROVER_assume( segment != NULL );
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue, &segment->xQueueItem );
}
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xTxSegments );
if( nondet_bool() )
{
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
__CPROVER_assume( segment != NULL );
vListInitialiseItem( &segment->xSegmentItem );
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xTxSegments, &segment->xQueueItem );
}
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xPriorityQueue );
extern List_t xSegmentList;
vListInitialise( &xSegmentList );
/****************************************************************
* Specification and proof of CheckOptions inner loop
****************************************************************/
/* Preconditions */
/* CBMC model of pointers limits the size of the buffer */
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
/* Both preconditions are required to avoid integer overflow in the */
/* pointer offset of the pointer pucPtr + uxIndex + 8 */
__CPROVER_assume( uxIndex <= buffer_size );
__CPROVER_assume( uxIndex + 8 <= buffer_size );
/* Assuming quite a bit more about the initialization of pxSocket */
__CPROVER_assume( pucPtr != NULL );
__CPROVER_assume( pxSocket != NULL );
prvReadSackOption( pucPtr, uxIndex, pxSocket );
/* No postconditions required */
}

View File

@ -0,0 +1,19 @@
{
"ENTRY": "CheckOptionsInner",
"CBMCFLAGS": [
"--unwind 1",
"--unwindset prvTCPWindowTxCheckAck.1:2,prvTCPWindowFastRetransmit.2:2"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,100 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h"
#include "cbmc.h"
/****************************************************************
* Signature of the function under test
****************************************************************/
int32_t __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag );
/****************************************************************
* Declare the buffer size external to the harness so it can be
* accessed by the preconditions of prvReadSackOption, and give the
* buffer size an unconstrained value in the harness itself.
****************************************************************/
size_t buffer_size;
/****************************************************************
* Function contract proved correct by CheckOptionsInner
****************************************************************/
void __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvReadSackOption( const uint8_t * const pucPtr,
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket )
{
/* Preconditions */
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
"prvReadSackOption: buffer_size < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( uxIndex <= buffer_size,
"prvReadSackOption: uxIndex <= buffer_size" );
__CPROVER_assert( uxIndex + 8 <= buffer_size,
"prvReadSackOption: uxIndex + 8 <= buffer_size" );
__CPROVER_assert( pucPtr != NULL,
"prvReadSackOption: pucPtr != NULL" );
__CPROVER_assert( pxSocket != NULL,
"prvReadSackOption: pxSocket != NULL" );
/* No postconditions required */
}
/****************************************************************
* Proof of prvSingleStepTCPHeaderOptions function contract
****************************************************************/
void harness()
{
/* Give buffer_size an unconstrained value */
size_t buf_size;
buffer_size = buf_size;
uint8_t * pucPtr = malloc( buffer_size );
size_t uxTotalLength;
FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
BaseType_t xHasSYNFlag;
/****************************************************************
* Specification and proof of CheckOptions outer loop
****************************************************************/
/* CBMC model of pointers limits the size of the buffer */
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
/* Preconditions */
__CPROVER_assume( 8 <= buffer_size ); /* ulFirst and ulLast */
__CPROVER_assume( pucPtr != NULL );
__CPROVER_assume( uxTotalLength <= buffer_size );
__CPROVER_assume( pxSocket != NULL );
int32_t index = __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions( pucPtr,
uxTotalLength,
pxSocket,
xHasSYNFlag );
/* Postconditions */
__CPROVER_assert( ( ( index == -1 ) || ( index == 1 ) || ( index <= uxTotalLength ) ),
"prvSingleStepTCPHeaderOptions: index <= uxTotalLength" );
}

View File

@ -0,0 +1,24 @@
{
"ENTRY": "CheckOptionsOuter",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions.2:32"
],
"OPT":
[
"--export-file-local-symbols"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_Reception.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,104 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "FreeRTOS_ARP.h"
/* Static members defined in FreeRTOS_DHCP.c */
extern DHCPData_t xDHCPData;
extern Socket_t xDHCPSocket;
void prvCreateDHCPSocket();
/* Static member defined in freertos_api.c */
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
extern uint32_t GetNetworkBuffer_failure_count;
#endif
/****************************************************************
* The signature of the function under test.
****************************************************************/
void vDHCPProcess( BaseType_t xReset,
eDHCPState_t eExpectedState );
/****************************************************************
* Abstract prvProcessDHCPReplies proved memory safe in ProcessDHCPReplies.
****************************************************************/
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
{
return nondet_BaseType();
}
/****************************************************************
* The proof of vDHCPProcess
****************************************************************/
void harness()
{
BaseType_t xReset;
eDHCPState_t eExpectedState;
/****************************************************************
* Initialize the counter used to bound the number of times
* GetNetworkBufferWithDescriptor can fail.
****************************************************************/
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
GetNetworkBuffer_failure_count = 0;
#endif
/****************************************************************
* Assume a valid socket in most states of the DHCP state machine.
*
* The socket is created in the eWaitingSendFirstDiscover state.
* xReset==True resets the state to eWaitingSendFirstDiscover.
****************************************************************/
if( !( ( xDHCPData.eDHCPState == eInitialWait ) ||
( xReset != pdFALSE ) ) )
{
prvCreateDHCPSocket();
__CPROVER_assume( xDHCPSocket != NULL );
}
vDHCPProcess( xReset, eExpectedState );
}

View File

@ -0,0 +1,56 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "DHCPProcess",
# Minimal buffer size for maximum coverage, see harness for details.
"BUFFER_SIZE": 299,
# The number of times GetNetworkBufferWithDescriptor can be allowed to fail
# (plus 1).
"FAILURE_BOUND": 2,
"CBMCFLAGS": "--unwind 4 --unwindset strlen.0:11,memcmp.0:7,prvProcessDHCPReplies.0:8,prvCreatePartDHCPMessage.0:{FAILURE_BOUND} --nondet-static --flush",
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
],
"DEF":
[
"BUFFER_SIZE={BUFFER_SIZE}",
"CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL=1",
"CBMC_GETNETWORKBUFFER_FAILURE_BOUND={FAILURE_BOUND}"
]
}

View File

@ -0,0 +1,28 @@
This is the memory safety proof for DHCPProcess function, which is the
function that triggers the DHCP protocol.
The main stubs in this proof deal with buffer management, which assume
that the buffer is large enough to accomodate a DHCP message plus a
few additional bytes for options (which is the last, variable-sized
field in a DHCP message). We have abstracted away sockets, concurrency
and third-party code. For more details, please check the comments on
the harness file.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* FreeRTOS_sendto
* FreeRTOS_setsockopt
* FreeRTOS_socket
* ulRand
* vARPSendGratuitous
* vApplicationIPNetworkEventHook
* vLoggingPrintf
* vPortEnterCritical
* vPortExitCritical
* vReleaseNetworkBufferAndDescriptor
* vSocketBind
* vSocketClose

View File

@ -0,0 +1,16 @@
{ "expected-missing-functions":
[
"vPortEnterCritical",
"vPortExitCritical",
"vSocketBind",
"vSocketClose",
"vTaskSetTimeOutState",
"xTaskGetTickCount",
"xTaskGetCurrentTaskHandle",
"xQueueGenericSend",
"xApplicationGetRandomNumber",
"vLoggingPrintf"
],
"proof-name": "DHCPProcess",
"proof-root": "tools/cbmc/proofs"
}

View File

@ -0,0 +1,49 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DHCP.h"
/*
* The harness test proceeds to call IsDHCPSocket with an unconstrained value
*/
void harness()
{
Socket_t xSocket;
BaseType_t xResult;
xResult = xIsDHCPSocket( xSocket );
}

View File

@ -0,0 +1,40 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "IsDHCPSocket",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto"
]
}

View File

@ -0,0 +1 @@
This is the memory safety proof for IsDCHPSocket.

View File

@ -0,0 +1,24 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_IP_Private.h"
/* Function prvParseDNSReply is proven to be correct separately.
* The proof can be found here: https://github.com/aws/amazon-freertos/tree/master/tools/cbmc/proofs/ParseDNSReply */
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength,
BaseType_t xExpected )
{
}
void harness()
{
NetworkBufferDescriptor_t xNetworkBuffer;
xNetworkBuffer.pucEthernetBuffer = malloc( sizeof( UDPPacket_t ) + sizeof( DNSMessage_t ) );
ulDNSHandlePacket( &xNetworkBuffer );
}

View File

@ -0,0 +1,12 @@
{
"ENTRY": "DNShandlePacket",
"CBMCFLAGS": "--unwind 1",
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto"
],
"DEF":
[
]
}

View File

@ -0,0 +1,17 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_IP_Private.h"
void harness()
{
if( ipconfigUSE_DNS_CACHE != 0 )
{
FreeRTOS_dnsclear();
}
}

View File

@ -0,0 +1,20 @@
{
"ENTRY": "DNSclear",
################################################################
# This configuration flag uses DNS cache
"USE_CACHE":1,
"CBMCFLAGS":
[
"--unwind 1",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto"
],
"DEF":
[
"ipconfigUSE_DNS_CACHE={USE_CACHE}"
]
}

View File

@ -0,0 +1,171 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "cbmc.h"
uint32_t FreeRTOS_dnslookup( const char * pcHostName );
Socket_t DNS_CreateSocket( TickType_t uxReadTimeout_ticks );
void DNS_CloseSocket( Socket_t xDNSSocket );
void DNS_ReadReply( Socket_t xDNSSocket,
struct freertos_sockaddr * xAddress,
struct xDNSBuffer * pxDNSBuf );
uint32_t DNS_SendRequest( Socket_t xDNSSocket,
struct freertos_sockaddr * xAddress,
struct xDNSBuffer * pxDNSBuf );
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength,
BaseType_t xExpected );
/****************************************************************
* We abstract:
*
* All kernel task scheduling functions since we are doing
* sequential verification and the sequential verification of these
* sequential primitives is done elsewhere.
*
* Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
*
* DNS_ParseDNSReply proved memory safe elsewhere
*
* prvCreateDNSMessage
*
* This proof assumes the length of pcHostName is bounded by
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
* bound the iterations of strcmp.
****************************************************************/
/****************************************************************
* Abstract DNS_ParseDNSReply proved memory safe in ParseDNSReply.
*
* We stub out his function to fill the payload buffer with
* unconstrained data and return an unconstrained size.
*
* The function under test uses only the return value of this
* function.
****************************************************************/
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength,
BaseType_t xExpected )
{
uint32_t size;
__CPROVER_havoc_object( pucUDPPayloadBuffer );
return size;
}
/****************************************************************
* Abstract DNS_SendRequest
*
* We stub out this function with return constraint of true or false
*
****************************************************************/
uint32_t DNS_SendRequest( Socket_t xDNSSocket,
struct freertos_sockaddr * xAddress,
struct xDNSBuffer * pxDNSBuf )
{
uint32_t ret;
__CPROVER_assume( ret >= 0 );
__CPROVER_assume( ret <= 1 );
return ret;
}
/****************************************************************
* Abstract DNS_ReadReply
*
* We stub out this function which returned a dns_buffer filled with random data
*
****************************************************************/
void DNS_ReadReply( Socket_t xDNSSocket,
struct freertos_sockaddr * xAddress,
struct xDNSBuffer * pxDNSBuf )
{
int len;
pxDNSBuf->pucPayloadBuffer = safeMalloc( len );
pxDNSBuf->uxPayloadLength = len;
__CPROVER_assume( len < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( pxDNSBuf->pucPayloadBuffer != NULL );
__CPROVER_havoc_slice( pxDNSBuf->pucPayloadBuffer, pxDNSBuf->uxPayloadSize );
}
void DNS_CloseSocket( Socket_t xDNSSocket )
{
}
Socket_t DNS_CreateSocket( TickType_t uxReadTimeout_ticks )
{
Socket_t sock;
return sock;
}
uint32_t FreeRTOS_dnslookup( const char * pcHostName )
{
int ret;
__CPROVER_assume( ret < 0xFFFF );
__CPROVER_assume( ret > 0 );
return ret;
}
/****************************************************************
* Abstract prvCreateDNSMessage
*
* This function writes a header, a hostname, and a constant amount of
* data into the payload buffer, and returns the amount of data
* written. This abstraction just fills the entire buffer with
* unconstrained data and returns and unconstrained length.
****************************************************************/
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
const char * pcHostName,
TickType_t uxIdentifier )
{
__CPROVER_havoc_object( pucUDPPayloadBuffer );
size_t size;
return size;
}
/****************************************************************
* The proof for FreeRTOS_gethostbyname.
****************************************************************/
void harness()
{
size_t len;
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len );
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
__CPROVER_assume( pcHostName != NULL );
pcHostName[ len - 1 ] = NULL;
FreeRTOS_gethostbyname( pcHostName );
}

View File

@ -0,0 +1,35 @@
{
"ENTRY": "DNSgetHostByName",
################################################################
# This configuration sets callback to 0.
# It also sets MAX_HOSTNAME_LEN to 10 to bound strcmp.
# According to the specification MAX_HOST_NAME is upto 255.
"callback": 0,
"MAX_HOSTNAME_LEN": 10,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}",
"--unwindset prvGetHostByNameOp_WithRetry.0:{HOSTNAME_UNWIND}",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
],
"DEF":
[
"ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}"
]
}

View File

@ -0,0 +1,9 @@
{ "expected-missing-functions":
[
"vLoggingPrintf",
"xApplicationGetRandomNumber",
"xTaskGetTickCount"
],
"proof-name": "DNSgetHostByName",
"proof-root": "tools/cbmc/proofs"
}

View File

@ -0,0 +1,113 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "cbmc.h"
/****************************************************************
* We abstract:
*
* All kernel task scheduling functions since we are doing
* sequential verification and the sequential verification of these
* sequential primitives is done elsewhere.
*
* Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
*
* DNS_ParseDNSReply proved memory safe elsewhere
*
* prvCreateDNSMessage
*
* This proof assumes the length of pcHostName is bounded by
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
* bound the iterations of strcmp.
****************************************************************/
/****************************************************************
* Abstract DNS_ParseDNSReply proved memory safe in ParseDNSReply.
*
* We stub out his function to fill the payload buffer with
* unconstrained data and return an unconstrained size.
*
* The function under test uses only the return value of this
* function.
****************************************************************/
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength,
BaseType_t xExpected )
{
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
"Precondition: pucUDPPayloadBuffer != NULL" );
__CPROVER_havoc_object( pucUDPPayloadBuffer );
return nondet_uint32();
}
/****************************************************************
* Abstract prvCreateDNSMessage
*
* This function writes a header, a hostname, and a constant amount of
* data into the payload buffer, and returns the amount of data
* written. This abstraction just fills the entire buffer with
* unconstrained data and returns and unconstrained length.
****************************************************************/
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
const char * pcHostName,
TickType_t uxIdentifier )
{
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
"Precondition: pucUDPPayloadBuffer != NULL" );
__CPROVER_assert( pcHostName != NULL,
"Precondition: pcHostName != NULL" );
__CPROVER_havoc_object( pucUDPPayloadBuffer );
return nondet_sizet();
}
/****************************************************************
* A stub for a function callback.
****************************************************************/
void func( const char * pcHostName,
void * pvSearchID,
uint32_t ulIPAddress )
{
}
/****************************************************************
* The proof for FreeRTOS_gethostbyname_a.
****************************************************************/
void harness()
{
size_t len;
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len );
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
__CPROVER_assume( pcHostName != NULL );
pcHostName[ len - 1 ] = NULL;
FOnDNSEvent pCallback = func;
TickType_t xTimeout;
void * pvSearchID;
FreeRTOS_gethostbyname_a( pcHostName, pCallback, pvSearchID, xTimeout );
}

View File

@ -0,0 +1,31 @@
{
"ENTRY": "DNSgetHostByName_a",
################################################################
# This configuration flag sets callback to 1. It also sets MAX_HOSTNAME_LEN to 10 and MAX_REQ_SIZE to 50 for performance issues.
# According to the specification MAX_HOST_NAME is upto 255.
"callback": 1,
"MAX_HOSTNAME_LEN": 10,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},prvGetHostByName.0:{HOSTNAME_UNWIND},prvProcessDNSCache.0:5,strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},xTaskResumeAll.0:{HOSTNAME_UNWIND},xTaskResumeAll.1:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto"
],
"DEF":
[
"ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
# This value is defined only when ipconfigUSE_DNS_CACHE==1
"ipconfigDNS_CACHE_NAME_LENGTH=254"
]
}

View File

@ -0,0 +1,13 @@
{ "expected-missing-functions":
[
"vLoggingPrintf",
"xApplicationGetRandomNumber",
"vListInsertEnd",
"vTaskSetTimeOutState",
"vTaskSuspendAll",
"xTaskGetTickCount",
"xTaskResumeAll"
],
"proof-name": "DNSgetHostByName_a",
"proof-root": "tools/cbmc/proofs"
}

View File

@ -0,0 +1,71 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_IP_Private.h"
/* This proof assumes the length of pcHostName is bounded by MAX_HOSTNAME_LEN. This also abstracts the concurrency. */
void vDNSInitialise( void );
void vDNSSetCallBack( const char * pcHostName,
void * pvSearchID,
FOnDNSEvent pCallbackFunction,
TickType_t xTimeout,
TickType_t xIdentifier );
void * safeMalloc( size_t xWantedSize ) /* Returns a NULL pointer if the wanted size is 0. */
{
if( xWantedSize == 0 )
{
return NULL;
}
uint8_t byte;
return byte ? malloc( xWantedSize ) : NULL;
}
/* Abstraction of xTaskCheckForTimeOut from task pool. This also abstracts the concurrency. */
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait )
{
}
/* Abstraction of xTaskResumeAll from task pool. This also abstracts the concurrency. */
BaseType_t xTaskResumeAll( void )
{
}
/* The function func mimics the callback function.*/
void func( const char * pcHostName,
void * pvSearchID,
uint32_t ulIPAddress )
{
}
void harness()
{
vDNSInitialise(); /* We initialize the callbacklist in order to be able to check for functions that timed out. */
size_t pvSearchID;
FOnDNSEvent pCallback = func;
TickType_t xTimeout;
TickType_t xIdentifier;
size_t len;
__CPROVER_assume( len >= 0 && len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len );
if( len && pcHostName )
{
pcHostName[ len - 1 ] = NULL;
}
vDNSSetCallBack( pcHostName, &pvSearchID, pCallback, xTimeout, xIdentifier ); /* Add an item to be able to check the cancel function if the list is non-empty. */
FreeRTOS_gethostbyname_cancel( &pvSearchID );
}

View File

@ -0,0 +1,29 @@
{
"ENTRY": "DNSgetHostByName_cancel",
################################################################
# This configuration flag sets callback to 1. It also sets MAX_HOSTNAME_LEN to 10 for performance issues.
# According to the specification MAX_HOST_NAME is upto 255.
"callback": 1,
"MAX_HOSTNAME_LEN": 10,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvProcessDNSCache.0:5,strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},vDNSCheckCallBack.0:2,strcpy.0:{HOSTNAME_UNWIND}",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
],
"DEF":
[
"ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
# This value is defined only when ipconfigUSE_DNS_CACHE==1
"ipconfigDNS_CACHE_NAME_LENGTH=254"
]
}

View File

@ -0,0 +1,42 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_IP_Private.h"
/* This assumes that the length of the hostname is bounded by MAX_HOSTNAME_LEN. */
void * safeMalloc( size_t xWantedSize )
{
if( xWantedSize == 0 )
{
return NULL;
}
uint8_t byte;
return byte ? malloc( xWantedSize ) : NULL;
}
void harness()
{
if( ipconfigUSE_DNS_CACHE != 0 )
{
size_t len;
__CPROVER_assume( len >= 0 && len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len ); /* malloc is replaced by safeMalloc */
if( len && pcHostName )
{
pcHostName[ len - 1 ] = NULL;
}
if( pcHostName ) /* guarding against NULL pointer */
{
FreeRTOS_dnslookup( pcHostName );
}
}
}

View File

@ -0,0 +1,26 @@
{
"ENTRY": "DNSlookup",
################################################################
# This configuration uses DNS cache and the MAX_HOSTNAME_LEN is set to 255 according to the specification
"MAX_HOSTNAME_LEN": 255,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"USE_CACHE": 1,
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvProcessDNSCache.0:5,strcmp.0:{HOSTNAME_UNWIND}",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
],
"DEF":
[
"ipconfigUSE_DNS_CACHE={USE_CACHE}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}"
],
"OPT" : "-m32"
}

View File

@ -0,0 +1,41 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "SendEventToIPTask",
"CBMCFLAGS": [
"--unwind 1",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
]
}

View File

@ -0,0 +1,13 @@
This is the memory safety proof for xSendEventToIPTask, a function used
for sending different events to IP-Task. We have abstracted away queues.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* uxQueueMessagesWaiting
* xQueueGenericSend
The coverage is imperfect (97%) because xSendEventToIPTask always
calls xSendEventStructToIPTask with xTimeout==0.

View File

@ -0,0 +1,45 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
/* The harness test proceeds to call SendEventToIPTask with an unconstrained value */
void harness()
{
eIPEvent_t eEvent;
xSendEventToIPTask( eEvent );
}

View File

@ -0,0 +1,174 @@
default: report
# ____________________________________________________________________
# CBMC binaries
#
GOTO_CC = @GOTO_CC@
GOTO_INSTRUMENT = goto-instrument
GOTO_ANALYZER = goto-analyzer
VIEWER = cbmc-viewer
# ____________________________________________________________________
# Variables
#
# Naming scheme:
# ``````````````
# FOO is the concatenation of the following:
# FOO2: Set of command line
# C_FOO: Value of $FOO common to all harnesses, set in this file
# O_FOO: Value of $FOO specific to the OS we're running on, set in the
# makefile for the operating system
# H_FOO: Value of $FOO specific to a particular harness, set in the
# makefile for that harness
ENTRY = $(H_ENTRY)
OBJS = $(H_OBJS)
INC = \
$(INC2) \
$(C_INC) $(O_INC) $(H_INC) \
# empty
CFLAGS = \
$(CFLAGS2) \
$(C_DEF) $(O_DEF) $(H_DEF) $(DEF) \
$(C_OPT) $(O_OPT) $(H_OPT) $(OPT) \
-m32 \
# empty
CBMCFLAGS = \
--flush \
$(CBMCFLAGS2) \
$(C_CBMCFLAGS) $(O_CBMCFLAGS) $(H_CBMCFLAGS) \
# empty
INSTFLAGS = \
$(INSTFLAGS2) \
$(C_INSTFLAGS) $(O_INSTFLAGS) $(H_INSTFLAGS) \
# empty
# ____________________________________________________________________
# Rules
#
# Rules for patching
patch:
cd $(PROOFS)/../patches && ./patch.py
unpatch:
cd $(PROOFS)/../patches && ./unpatch.py
# ____________________________________________________________________
# Rules
#
# Rules for building the CBMC harness
C_SOURCES = $(patsubst %.goto,%.c,$(H_OBJS_EXCEPT_HARNESS))
# Build each goto-binary out-of-source (i.e. in a 'gotos' directory
# underneath each proof directory, to make it safe to build all proofs
# in parallel
OOS_OBJS = $(patsubst %.c,gotos/%.goto,$(C_SOURCES))
CWD=$(abspath .)
gotos/%.goto: %.c
mkdir -p $(dir $@)
$(GOTO_CC) @COMPILE_ONLY@ @RULE_OUTPUT@ $(INC) $(CFLAGS) @RULE_INPUT@
queue_datastructure.h: gotos/$(FREERTOS)/freertos_kernel/queue.goto
python3 @TYPE_HEADER_SCRIPT@ --binary $(CWD)/gotos$(FREERTOS)/freertos_kernel/queue.goto --c-file $(FREERTOS)/freertos_kernel/queue.c
$(ENTRY)_harness.goto: $(ENTRY)_harness.c $(H_GENERATE_HEADER)
$(GOTO_CC) @COMPILE_ONLY@ @RULE_OUTPUT@ $(INC) $(CFLAGS) $(ENTRY)_harness.c
$(ENTRY)1.goto: $(ENTRY)_harness.goto $(OOS_OBJS)
$(GOTO_CC) @COMPILE_LINK@ @RULE_OUTPUT@ --function harness @RULE_INPUT@
$(ENTRY)2.goto: $(ENTRY)1.goto
$(GOTO_INSTRUMENT) --add-library @RULE_INPUT@ @RULE_OUTPUT@ \
> $(ENTRY)2.txt 2>&1
$(ENTRY)3.goto: $(ENTRY)2.goto
$(GOTO_INSTRUMENT) --drop-unused-functions @RULE_INPUT@ @RULE_OUTPUT@ \
> $(ENTRY)3.txt 2>&1
$(ENTRY)4.goto: $(ENTRY)3.goto
$(GOTO_INSTRUMENT) $(INSTFLAGS) --slice-global-inits @RULE_INPUT@ @RULE_OUTPUT@ \
> $(ENTRY)4.txt 2>&1
# ____________________________________________________________________
# After running goto-instrument to remove function bodies the unused
# functions need to be dropped again.
$(ENTRY)5.goto: $(ENTRY)4.goto
$(GOTO_INSTRUMENT) --drop-unused-functions @RULE_INPUT@ @RULE_OUTPUT@ \
> $(ENTRY)5.txt 2>&1
$(ENTRY).goto: $(ENTRY)5.goto
@CP@ @RULE_INPUT@ @RULE_OUTPUT@
# ____________________________________________________________________
# Rules
#
# Rules for running CBMC
goto:
$(MAKE) -B $(ENTRY).goto
# Ignore the return code for CBMC, so that we can still generate the
# report if the proof failed. If the proof failed, we separately fail
# the entire job using the check-cbmc-result rule.
cbmc.txt: $(ENTRY).goto
-cbmc $(CBMCFLAGS) $(SOLVER) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1
property.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ > $@ 2>&1
coverage.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ > $@ 2>&1
cbmc: cbmc.txt
property: property.xml
coverage: coverage.xml
report: cbmc.txt property.xml coverage.xml
$(VIEWER) \
--goto $(ENTRY).goto \
--srcdir $(FREERTOS_PLUS_TCP) \
--blddir $(FREERTOS_PLUS_TCP) \
--htmldir html \
--srcexclude "(.@FORWARD_SLASH@doc|.@FORWARD_SLASH@tests|.@FORWARD_SLASH@vendors)" \
--result cbmc.txt \
--property property.xml \
--block coverage.xml
# This rule depends only on cbmc.txt and has no dependents, so it will
# not block the report from being generated if it fails. This rule is
# intended to fail if and only if the CBMC safety check that emits
# cbmc.txt yielded a proof failure.
check-cbmc-result: cbmc.txt
grep -e "^VERIFICATION SUCCESSFUL" $^
# ____________________________________________________________________
# Rules
#
# Rules for cleaning up
clean:
@RM@ $(OBJS) $(ENTRY).goto
@RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt
@RM@ cbmc.txt property.xml coverage.xml TAGS TAGS-*
@RM@ *~ \#*
@RM@ queue_datastructure.h
veryclean: clean
@RM_RECURSIVE@ html
@RM_RECURSIVE@ gotos
distclean: veryclean
cd $(PROOFS)/../patches && ./unpatch.py
cd $(PROOFS) && ./make-remove-makefiles.py

View File

@ -0,0 +1,45 @@
{
"FREERTOS_PLUS_TCP": [ " ../../.." ],
"PROOFS": [ "." ],
"DEF ": [
"WIN32",
"WINVER=0x400",
"_CONSOLE",
"_CRT_SECURE_NO_WARNINGS",
"_DEBUG",
"_WIN32_WINNT=0x0500",
"__PRETTY_FUNCTION__=__FUNCTION__",
"__free_rtos__",
"CBMC",
"'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'",
"'configPRECONDITION(X)=__CPROVER_assume(X)'",
"'_static='",
"'_volatile='"
],
"INC ": [
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/include",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/portable/MSVC-MingW",
"$(FREERTOS_PLUS_TCP)/source/include",
"$(FREERTOS_PLUS_TCP)/source/portable/Compiler/MSVC",
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/patches",
"$(FREERTOS_PLUS_TCP)/test/cbmc/windows",
"$(FREERTOS_PLUS_TCP)/test/cbmc/windows2"
],
"CBMCFLAGS ": [
"--object-bits 7",
"--32",
"--bounds-check",
"--pointer-check"
],
"FORWARD_SLASH": ["/"],
"TYPE_HEADERS": [
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.c"
]
}

View File

@ -0,0 +1,36 @@
{
"GOTO_CC": [
"goto-cc"
],
"COMPILE_LINK": [
"-o"
],
"COMPILE_ONLY": [
"-c",
"-o"
],
"RULE_INPUT": [
"$^"
],
"RULE_OUTPUT": [
"$@"
],
"RULE_GOTO": [
"%.goto : %.c"
],
"INC": [
"$(PROOFS)/../windows"
],
"RM": [
"$(RM)"
],
"RM_RECURSIVE": [
"$(RM) -r"
],
"CP": [
"cp"
],
"TYPE_HEADER_SCRIPT": [
"$(PROOFS)/make_type_header_files.py"
]
}

View File

@ -0,0 +1,44 @@
{
"DEF": [
"WIN32"
],
"GOTO_CC": [
"goto-cl"
],
"COMPILE_LINK": [
"/Fe"
],
"COMPILE_ONLY": [
"/c",
"/Fo"
],
"RULE_INPUT": [
"$**"
],
"RULE_OUTPUT": [
"$@"
],
"RULE_GOTO": [
".c.goto:"
],
"OPT": [
"/wd4210",
"/wd4127",
"/wd4214",
"/wd4201",
"/wd4244",
"/wd4310"
],
"RM": [
"del"
],
"RM_RECURSIVE": [
"del /s"
],
"CP": [
"copy"
],
"TYPE_HEADER_SCRIPT": [
"$(PROOFS)\\make_type_header_files.py"
]
}

View File

@ -0,0 +1,68 @@
# The proof depends on one parameter:
# NETWORK_BUFFER_SIZE is the size of the network buffer being parsed
# The buffer size must be bounded because we must bound the number of
# iterations loops iterating over the buffer.
{
"ENTRY": "ParseDNSReply",
################################################################
# This is the network buffer size.
# Reasonable values are size > 12 = sizeof(xDNSMessage)
"NETWORK_BUFFER_SIZE": 40,
################################################################
# This is the size of the buffer into which the name is copied.
# Set to any positive value.
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
# In the proof, NAME_SIZE >= 4 required for good coverage.
"NAME_SIZE": "10",
################################################################
# Loop prvParseDNSReply.0:
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 915
"PARSELOOP0": "prvParseDNSReply.0",
# M = sizeof( DNSMessage_t ) = 12
# U = sizeof( uint32_t) = 4
# Loop bound is (NETWORK_BUFFER_SIZE - M) div (U+1) + 1 tight for SIZE >= M
# Loop bound is 1 for 0 <= SIZE < M
"PARSELOOP0_UNWIND":
"__eval 1 if {NETWORK_BUFFER_SIZE} < 12 else ({NETWORK_BUFFER_SIZE} - 12) / 5 + 1",
################################################################
# Loop prvParseDNSReply.1:
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 989
"PARSELOOP1": "prvParseDNSReply.1",
# A = sizeof( DNSAnswerRecord_t ) = 10
# M = sizeof( DNSMessage_t ) = 12
# U = sizeof( uint32_t) = 4
# Loop bound is (NETWORK_BUFFER_SIZE - M - A) div (A+1) + A + 1 tight
# for SIZE >= M + A
# Loop bound is (NETWORK_BUFFER_SIZE - M) + 1 for M <= SIZE < M + A
# Loop bound is 1 for 0 <= SIZE < M
"PARSELOOP1_UNWIND":
"__eval 1 if {NETWORK_BUFFER_SIZE} < 12 else ({NETWORK_BUFFER_SIZE} - 11 if {NETWORK_BUFFER_SIZE} < 22 else ({NETWORK_BUFFER_SIZE} - 12 - 10) / 11 + 11)",
################################################################
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset {PARSELOOP0}:{PARSELOOP0_UNWIND},{PARSELOOP1}:{PARSELOOP1_UNWIND},prvProcessDNSCache.0:5"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
],
"DEF":
[
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
"NAME_SIZE={NAME_SIZE}"
]
}

View File

@ -0,0 +1,130 @@
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "list.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DNS_Parser.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "IPTraceMacroDefaults.h"
#include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected );
/****************************************************************
* Abstraction of DNS_ReadNameField proved in ReadNameField
****************************************************************/
size_t DNS_ReadNameField( const uint8_t * pucByte,
size_t uxRemainingBytes,
char * pcName,
size_t uxDestLen )
{
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
"NAME_SIZE < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( NAME_SIZE >= 4,
"NAME_SIZE >= 4 required for good coverage." );
/* Preconditions */
__CPROVER_assert( uxRemainingBytes < CBMC_MAX_OBJECT_SIZE,
"ReadNameField: uxRemainingBytes < CBMC_MAX_OBJECT_SIZE)" );
__CPROVER_assert( uxDestLen < CBMC_MAX_OBJECT_SIZE,
"ReadNameField: uxDestLen < CBMC_MAX_OBJECT_SIZE)" );
__CPROVER_assert( uxRemainingBytes <= NETWORK_BUFFER_SIZE,
"ReadNameField: uxRemainingBytes <= NETWORK_BUFFER_SIZE)" );
/* This precondition in the function contract for prvReadNameField
* fails because prvCheckOptions called prvReadNameField with the
* constant value 254.
* __CPROVER_assert(uxDestLen <= NAME_SIZE,
* "ReadNameField: uxDestLen <= NAME_SIZE)");
*/
__CPROVER_assert( pucByte != NULL,
"ReadNameField: pucByte != NULL )" );
__CPROVER_assert( pcName != NULL,
"ReadNameField: pcName != NULL )" );
__CPROVER_assert( uxDestLen > 0,
"ReadNameField: uxDestLen > 0)" );
/* Return value */
size_t index;
/* Postconditions */
__CPROVER_assume( index <= uxDestLen + 1 && index <= uxRemainingBytes );
return index;
}
/****************************************************************
* Abstraction of DNS_SkipNameField proved in SkipNameField
****************************************************************/
size_t DNS_SkipNameField( const uint8_t * pucByte,
size_t uxLength )
{
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
/* Preconditions */
__CPROVER_assert( uxLength < CBMC_MAX_OBJECT_SIZE,
"SkipNameField: uxLength < CBMC_MAX_OBJECT_SIZE)" );
__CPROVER_assert( uxLength <= NETWORK_BUFFER_SIZE,
"SkipNameField: uxLength <= NETWORK_BUFFER_SIZE)" );
__CPROVER_assert( pucByte != NULL,
"SkipNameField: pucByte != NULL)" );
/* Return value */
size_t index;
/* Postconditions */
__CPROVER_assume( index <= uxLength );
return index;
}
/****************************************************************
* Proof of prvParseDNSReply
****************************************************************/
void harness()
{
size_t uxBufferLength;
BaseType_t xExpected;
uint8_t * pucUDPPayloadBuffer = malloc( uxBufferLength );
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assume( uxBufferLength < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( uxBufferLength <= NETWORK_BUFFER_SIZE );
__CPROVER_assume( pucUDPPayloadBuffer != NULL );
uint32_t index = prvParseDNSReply( pucUDPPayloadBuffer,
uxBufferLength,
xExpected );
}

View File

@ -0,0 +1,48 @@
# The proof depends on one parameter:
# BUFFER_SIZE is the size of the buffer being parsed
# The buffer size must be bounded because we must bound the number of
# iterations loops iterating over the buffer.
{
"ENTRY": "ProcessDHCPReplies",
################################################################
# Buffer header: sizeof(DHCPMessage_t) = 241
# Buffer header: sizeof(DHCPMessage_IPv4_t) = 240
"BUFFER_HEADER": 240,
################################################################
# Buffer size
# Reasonable sizes are BUFFER_SIZE > BUFFER_HEADER
# Sizes smaller than this causes CBMC to fail in simplify_byte_extract
"BUFFER_SIZE": 252,
################################################################
# Buffer payload
"BUFFER_PAYLOAD": "__eval 1 if {BUFFER_SIZE} <= {BUFFER_HEADER} else {BUFFER_SIZE} - {BUFFER_HEADER} + 1",
################################################################
"CBMCFLAGS": [
# "--nondet-static",
"--unwind 1",
"--unwindset memcmp.0:7,prvProcessDHCPReplies.0:{BUFFER_PAYLOAD}"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto",
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_2.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/event_groups.goto",
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
],
"DEF":
[
"CBMC_DHCPMESSAGE_HEADER_SIZE={BUFFER_HEADER}",
"CBMC_FREERTOS_RECVFROM_BUFFER_BOUND={BUFFER_SIZE}"
]
}

View File

@ -0,0 +1,37 @@
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "FreeRTOS_ARP.h"
/****************************************************************
* Signature of function under test
****************************************************************/
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
/****************************************************************
* The proof for FreeRTOS_gethostbyname.
****************************************************************/
void harness()
{
/* Omitting model of an unconstrained xDHCPData because xDHCPData is */
/* the source of uninitialized data only on line 647 to set a */
/* transaction id is an outgoing message */
BaseType_t xExpectedMessageType;
prvProcessDHCPReplies( xExpectedMessageType );
}

View File

@ -0,0 +1 @@
This directory contains the proofs checked by CBMC. For each entry point of FreeRTOS-Plus-TCP tested, there is a directory that contains the test harness and cbmc configuration information needed to check the proof.

View File

@ -0,0 +1,55 @@
{
"ENTRY": "ReadNameField",
################################################################
#Enable DNS callbacks or else ReadNameField is not defined
"callbacks": "1",
################################################################
# This is the network buffer size. Set to any positive value.
"NETWORK_BUFFER_SIZE" : "10",
################################################################
# This is the size of the buffer into which the name is copied.
# Set to any positive value.
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
# In the proof, NAME_SIZE >= 4 required for good coverage.
"NAME_SIZE": "6",
################################################################
# Loop prvReadNameField.0:
# should be min of buffer size and name size
# but loop must be unwound at least once, so max of this and 1+1
"READLOOP0": "DNS_ReadNameField.0",
"READLOOP0_UNWIND": "__eval max(2, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}+1))",
################################################################
# Loop prvReadNameField.1:
# should be min of buffer size and name size
# but loop must be unwound at least twice, so max of this and 2+1
"READLOOP1": "DNS_ReadNameField.1",
"READLOOP1_UNWIND": "__eval max(3, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}))",
################################################################
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset {READLOOP0}:{READLOOP0_UNWIND},{READLOOP1}:{READLOOP1_UNWIND}"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
],
"DEF":
[
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
"NAME_SIZE={NAME_SIZE}",
"ipconfigDNS_USE_CALLBACKS={callbacks}",
"ipconfigDNS_CACHE_NAME_LENGTH=254"
]
}

View File

@ -0,0 +1,102 @@
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "list.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "IPTraceMacroDefaults.h"
#include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
size_t DNS_ReadNameField( const uint8_t * pucByte,
size_t uxRemainingBytes,
char * pcName,
size_t uxDestLen );
/****************************************************************
* The function under test is not defined in all configurations
****************************************************************/
#if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
/* DNS_ReadNameField is defined in this configuration */
#else
/* DNS_ReadNameField is not defined in this configuration, stub it. */
size_t DNS_ReadNameField( const uint8_t * pucByte,
size_t uxRemainingBytes,
char * pcName,
size_t uxDestLen )
{
return 0;
}
#endif /* if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) */
/****************************************************************
* Proof of DNS_ReadNameField function contract
****************************************************************/
void harness()
{
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
"NAME_SIZE < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( NAME_SIZE >= 4,
"NAME_SIZE >= 4 required for good coverage." );
size_t uxRemainingBytes;
size_t uxDestLen;
uint8_t * pucByte = malloc( uxRemainingBytes );
char * pcName = malloc( uxDestLen );
/* Preconditions */
__CPROVER_assume( uxRemainingBytes < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( uxDestLen < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( uxRemainingBytes <= NETWORK_BUFFER_SIZE );
__CPROVER_assume( uxDestLen <= NAME_SIZE );
__CPROVER_assume( pucByte != NULL );
__CPROVER_assume( pcName != NULL );
/* Avoid overflow on uxSourceLen - 1U with uxSourceLen == uxRemainingBytes */
/*__CPROVER_assume(uxRemainingBytes > 0); */
/* Avoid overflow on uxDestLen - 1U */
__CPROVER_assume( uxDestLen > 0 );
size_t index = DNS_ReadNameField( pucByte,
uxRemainingBytes,
pcName,
uxDestLen );
/* Postconditions */
__CPROVER_assert( index <= uxDestLen + 1 && index <= uxRemainingBytes,
"DNS_ReadNameField : index <= uxDestLen+1" );
}

View File

@ -0,0 +1,32 @@
{
"ENTRY": "SkipNameField",
################################################################
# This is the network buffer size. This can be set to any positive value.
"NETWORK_BUFFER_SIZE": 10,
################################################################
# Loop DNS_SkipNameField.0:
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 778
# bound should be half network buffer size, since chunk length is at least 2
"SKIPLOOP0": "DNS_SkipNameField.0",
"SKIPLOOP0_UNWIND": "__eval ({NETWORK_BUFFER_SIZE} + 1) / 2",
################################################################
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset {SKIPLOOP0}:{SKIPLOOP0_UNWIND}"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
],
"DEF":
[
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}"
]
}

View File

@ -0,0 +1,55 @@
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "list.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "IPTraceMacroDefaults.h"
#include "FreeRTOS_DNS_Parser.h"
#include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
size_t DNS_SkipNameField( const uint8_t * pucByte,
size_t uxLength );
/****************************************************************
* Proof of DNS_SkipNameField function contract
****************************************************************/
void harness()
{
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
size_t uxLength;
uint8_t * pucByte = malloc( uxLength );
/* Preconditions */
__CPROVER_assume( uxLength < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( uxLength <= NETWORK_BUFFER_SIZE );
__CPROVER_assume( pucByte != NULL );
size_t index = DNS_SkipNameField( pucByte, uxLength );
/* Postconditions */
__CPROVER_assert( index <= uxLength,
"DNS_SkipNameField: index <= uxLength" );
}

View File

@ -0,0 +1,31 @@
{
"ENTRY": "vSocketBind",
"ALLOW_SEND_WITHOUT_BIND":"1",
"ALLOW_ETHERNET_DRIVER_FILTER":"1",
"ALLOW_TCP":"1",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
"$(ENTRY)_harness.goto"
],
"INSTFLAGS":
[
],
"DEF":
[
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
"ipconfigUSE_TCP={ALLOW_TCP}",
"ipconfigETHERNET_DRIVER_FILTERS_PACKETS={ALLOW_ETHERNET_DRIVER_FILTER}"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
]
}

View File

@ -0,0 +1,68 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "memory_assignments.c"
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
{
uint16_t usResult;
return usResult;
}
BaseType_t xIPIsNetworkTaskReady( void )
{
/* Return true saying that the task is ready. */
return pdTRUE;
}
/* Random number generator provided by the application. In our case, CBMC provides
* an indeterministic value. */
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
if( nondet_bool() )
{
*pulNumber = nondet_uint32_t();
return 1;
}
else
{
*pulNumber = NULL;
return 0;
}
}
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
__CPROVER_assume( pxSocket != NULL );
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
struct freertos_sockaddr * pxBindAddress = safeMalloc( sizeof( struct freertos_sockaddr ) );
/* uxAddressLength is not used in this implementation. */
size_t uxAddressLength;
BaseType_t xInternal;
/* Call to init the socket list. */
vNetworkSocketsInit();
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
}

View File

@ -0,0 +1,28 @@
{
"ENTRY": "vSocketBind",
"ALLOW_SEND_WITHOUT_BIND":"1",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
"$(ENTRY)_harness.goto"
],
"INSTFLAGS":
[
],
"DEF":
[
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
"ipconfigUSE_TCP=1"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
]
}

View File

@ -0,0 +1,66 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "memory_assignments.c"
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
{
uint16_t usResult;
return usResult;
}
BaseType_t xIPIsNetworkTaskReady( void )
{
/* Return true saying that the task is ready. */
return pdTRUE;
}
/* Random number generator provided by the application. In our case, CBMC provides
* an indeterministic value. */
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
if( nondet_bool() )
{
*pulNumber = nondet_uint32_t();
return 1;
}
else
{
*pulNumber = NULL;
return 0;
}
}
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
__CPROVER_assume( pxSocket != NULL );
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
struct freertos_sockaddr * pxBindAddress = safeMalloc( sizeof( struct freertos_sockaddr ) );
/* uxAddressLength is not used in this implementation. */
size_t uxAddressLength;
BaseType_t xInternal;
/* Call to init the socket list. */
vNetworkSocketsInit();
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
}

View File

@ -0,0 +1,28 @@
{
"ENTRY": "vSocketBind",
"ALLOW_SEND_WITHOUT_BIND":"0",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
"$(ENTRY)_harness.goto"
],
"INSTFLAGS":
[
],
"DEF":
[
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
"ipconfigUSE_TCP=1"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
]
}

View File

@ -0,0 +1,70 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "memory_assignments.c"
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
{
uint16_t usResult;
return usResult;
}
BaseType_t xIPIsNetworkTaskReady( void )
{
/* Return true saying that the task is ready. */
return pdTRUE;
}
/* Random number generator provided by the application. In our case, CBMC provides
* an indeterministic value. */
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
if( nondet_bool() )
{
*pulNumber = nondet_uint32_t();
return 1;
}
else
{
*pulNumber = NULL;
return 0;
}
}
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
__CPROVER_assume( pxSocket != NULL );
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
/* malloc instead of safeMalloc since we do not allow socket without binding. */
struct freertos_sockaddr * pxBindAddress = malloc( sizeof( struct freertos_sockaddr ) );
__CPROVER_assume( pxBindAddress != NULL );
/* uxAddressLength is not used in this implementation. */
size_t uxAddressLength;
BaseType_t xInternal;
/* Call to init the socket list. */
vNetworkSocketsInit();
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
}

View File

@ -0,0 +1,39 @@
{
"ENTRY": "vSocketClose",
"CBMCFLAGS":
[
"--unwind 2"
],
"OBJS":
[
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
"$(ENTRY)_harness.goto"
],
"DEF":
[
{
"UDP_Only":[
"PROTOCOL=FREERTOS_IPPROTO_UDP",
"ipconfigUSE_TCP=1",
"ipconfigUSE_TCP_WIN=1",
"ipconfigHAS_DEBUG_PRINTF=0"
]
},
{
"TCP_Only":[
"PROTOCOL=FREERTOS_IPPROTO_TCP",
"ipconfigUSE_TCP=1",
"ipconfigUSE_TCP_WIN=1",
"ipconfigHAS_DEBUG_PRINTF=0"
]
}
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility",
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs"
]
}

View File

@ -0,0 +1,125 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "freertos_api.c"
#include "memory_assignments.c"
/* The memory safety of vTCPWindowDestroy has already been proved in
* proofs/TCPWin/vTCPWindowDestroy. */
void vTCPWindowDestroy( TCPWindow_t const * xWindow )
{
__CPROVER_assert( xWindow != NULL, "xWindow cannot be NULL" );
/* Do nothing. */
}
void harness()
{
size_t xRequestedSizeBytes;
TickType_t xBlockTimeTicks;
FreeRTOS_Socket_t * pxSocket = safeMalloc( sizeof( FreeRTOS_Socket_t ) );
/* Socket cannot be NULL or invalid for this proof. This is allowed since vSocketClose is called by IP task only. */
__CPROVER_assume( pxSocket != NULL );
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
/* Request a random number of bytes keeping in mind the maximum bound of CBMC. */
__CPROVER_assume( xRequestedSizeBytes < ( CBMC_MAX_OBJECT_SIZE - ipBUFFER_PADDING ) );
/* Non-deterministically malloc the callback function. */
pxSocket->pxUserWakeCallback = safeMalloc( sizeof( SocketWakeupCallback_t ) );
/* Non deterministically add an event group. */
if( nondet_bool() )
{
pxSocket->xEventGroup = xEventGroupCreate();
__CPROVER_assume( pxSocket->xEventGroup != NULL );
}
else
{
pxSocket->xEventGroup = NULL;
}
/* Create and fill the socket in the bound socket list. This socket will then be
* removed by a call to the vSocketClose. */
List_t BoundSocketList;
vListInitialise( &BoundSocketList );
/* Non-deterministically add the socket to bound socket list. */
if( nondet_bool() )
{
vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
pxSocket->xBoundSocketListItem.pxContainer = &( BoundSocketList );
vListInsertEnd( &BoundSocketList, &( pxSocket->xBoundSocketListItem ) );
}
else
{
pxSocket->xBoundSocketListItem.pxContainer = NULL;
}
/* See Configurations.json for details. Protocol can be UDP or TCP. */
pxSocket->ucProtocol = PROTOCOL;
NetworkBufferDescriptor_t * NetworkBuffer;
/* Get a network buffer descriptor with requested bytes. See the constraints
* on the number of requested bytes above. And block for random timer ticks. */
if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
{
pxSocket->u.xTCP.rxStream = malloc( sizeof( StreamBuffer_t ) );
pxSocket->u.xTCP.txStream = malloc( sizeof( StreamBuffer_t ) );
/* Non deterministically allocate/not-allocate the network buffer descriptor. */
if( nondet_bool() )
{
pxSocket->u.xTCP.pxAckMessage = pxGetNetworkBufferWithDescriptor( xRequestedSizeBytes, xBlockTimeTicks );
}
else
{
pxSocket->u.xTCP.pxAckMessage = NULL;
}
}
else if( pxSocket->ucProtocol == FREERTOS_IPPROTO_UDP )
{
/* Initialise the waiting packet list. */
vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
/* Non-deterministically either add/not-add item to the waiting packet list. */
if( nondet_bool() )
{
NetworkBuffer = pxGetNetworkBufferWithDescriptor( xRequestedSizeBytes, xBlockTimeTicks );
/* Assume non-NULL network buffer for this case. */
__CPROVER_assume( NetworkBuffer != NULL );
/* Initialise the buffer list item. */
vListInitialiseItem( &( NetworkBuffer->xBufferListItem ) );
/*Set the item owner as the buffer itself. */
listSET_LIST_ITEM_OWNER( &( NetworkBuffer->xBufferListItem ), ( void * ) NetworkBuffer );
/* Set the container of the buffer list item as the waiting packet list. */
NetworkBuffer->xBufferListItem.pxContainer = &( pxSocket->u.xUDP.xWaitingPacketsList );
/* Insert the list-item into the waiting packet list. */
vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( NetworkBuffer->xBufferListItem ) );
}
}
/* Call to init the socket list. */
vNetworkSocketsInit();
/* Call the function. */
vSocketClose( pxSocket );
/* No post checking to be done. */
}

View File

@ -0,0 +1,26 @@
{
"ENTRY": "vSocketWakeUpUser",
"CBMCFLAGS":
[
"--unwind 1"
],
"OBJS":
[
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
"$(ENTRY)_harness.goto"
],
"DEF":
[
"ipconfigSOCKET_HAS_USER_SEMAPHORE=1",
"ipconfigSOCKET_HAS_USER_WAKE_CALLBACK=1",
"ipconfigSUPPORT_SELECT_FUNCTION=1",
"configUSE_16_BIT_TICKS=0"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
]
}

View File

@ -0,0 +1,167 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h"
#include "memory_assignments.c"
/*********************************************************************************
*
* The below structure definitions are just copy pasted from the FreeRTOS-Kernel.
* To understand the proof, you need not understand the structures and they can
* be ignored safely.
*
********************************************************************************/
/* Define the bits used by Kernel. */
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
typedef struct EventGroupDef_t
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated;
#endif
} EventGroup_t;
typedef struct QueuePointers
{
int8_t * pcTail;
int8_t * pcReadFrom;
} QueuePointers_t;
typedef struct SemaphoreData
{
TaskHandle_t xMutexHolder;
UBaseType_t uxRecursiveCallCount;
} SemaphoreData_t;
typedef struct QueueDefinition
{
int8_t * pcHead;
int8_t * pcWriteTo;
union
{
QueuePointers_t xQueue;
SemaphoreData_t xSemaphore;
} u;
List_t xTasksWaitingToSend;
List_t xTasksWaitingToReceive;
volatile UBaseType_t uxMessagesWaiting;
UBaseType_t uxLength;
UBaseType_t uxItemSize;
volatile int8_t cRxLock;
volatile int8_t cTxLock;
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated;
#endif
#if ( configUSE_QUEUE_SETS == 1 )
struct QueueDefinition * pxQueueSetContainer;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxQueueNumber;
uint8_t ucQueueType;
#endif
} xQUEUE;
/********************************************************/
/********* End Kernel cut-paste section *****************/
/********************************************************/
/* The memory safety of xQueueGenericSend has been proved before.
* See github.com/FreeRTOS/FreeRTOS/FreeRTOS/Test/CBMC/proofs/Queue/QueueGenericSend.
*/
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
{
BaseType_t xResult;
/* These asserts are copied over from the original function itself. */
__CPROVER_assert( xQueue != NULL, "xQueue cannot be NULL" );
__CPROVER_assert( !( ( pvItemToQueue == NULL ) && ( xQueue->uxItemSize != ( UBaseType_t ) 0U ) ),
"If itemsize is non-zero, then pvItemToQueue cannot be NULL." );
__CPROVER_assert( !( ( xCopyPosition == queueOVERWRITE ) && ( xQueue->uxLength != 1 ) ),
"If length is one, then check the copy position" );
/* Return any random value. */
return xResult;
}
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet )
{
EventBits_t uxReturnBits;
/* The below asserts are copied over from the original function itself. */
__CPROVER_assert( xEventGroup != NULL,
"The event group cannot be NULL" );
__CPROVER_assert( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0,
"Cannot set Kernel bits" );
/* Return any random value. */
return uxReturnBits;
}
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
__CPROVER_assume( pxSocket != NULL );
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
pxSocket->pxUserWakeCallback = safeMalloc( sizeof( SocketWakeupCallback_t ) );
pxSocket->pxSocketSet = safeMalloc( sizeof( struct xSOCKET_SET ) );
if( pxSocket->pxSocketSet != NULL )
{
pxSocket->pxSocketSet->xSelectGroup = safeMalloc( sizeof( struct EventGroupDef_t ) );
/* The event group cannot be NULL. */
__CPROVER_assume( pxSocket->pxSocketSet->xSelectGroup != NULL );
}
pxSocket->pxUserSemaphore = safeMalloc( sizeof( xQUEUE ) );
if( pxSocket->pxUserSemaphore != NULL )
{
/* The item size must be zero since this queue will act as a semaphore. */
__CPROVER_assume( pxSocket->pxUserSemaphore->uxItemSize == 0 );
}
pxSocket->xEventGroup = safeMalloc( sizeof( struct EventGroupDef_t ) );
/* Call to init the socket list. */
vNetworkSocketsInit();
vSocketWakeUpUser( pxSocket );
}

View File

@ -0,0 +1,62 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "TCPHandleState",
"TX_DRIVER":1,
"RX_MESSAGES":1,
"CBMCFLAGS":
[
"--unwind 1",
"--unwindset prvWinScaleFactor.0:2",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP_Utils.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP_Timers.goto"
],
"DEF":
[
"ipconfigZERO_COPY_TX_DRIVER={TX_DRIVER}",
"ipconfigUSE_LINKED_RX_MESSAGES={RX_MESSAGES}",
"FREERTOS_TCP_ENABLE_VERIFICATION"
],
"INSTFLAGS":
[
"--remove-function-body prvTCPPrepareSend",
"--remove-function-body prvTCPReturnPacket"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
]
}

View File

@ -0,0 +1,22 @@
This is the memory safety proof for prvTCPHandleState.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* prvTCPPrepareSend (proved independently)
* prvTCPReturnPacket (proved independently)
* lTCPAddRxdata
* lTCPWindowRxCheck
* lTCPWindowTxAdd
* ulTCPWindowTxAck
* vTCPWindowInit
* xTCPWindowRxEmpty
* xTCPWindowTxDone
* uxStreamBufferGet
* vReleaseNetworkBufferAndDescriptor
* vSocketWakeUpUser
* xTaskGetTickCount

View File

@ -0,0 +1,101 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_TCP_IP.h"
#include "../../utility/memory_assignments.c"
/* Abstraction of xTaskGetCurrentTaskHandle */
TaskHandle_t xTaskGetCurrentTaskHandle( void )
{
static int xIsInit = 0;
static TaskHandle_t pxCurrentTCB;
TaskHandle_t xRandomTaskHandle; /* not initialized on purpose */
if( xIsInit == 0 )
{
pxCurrentTCB = xRandomTaskHandle;
xIsInit = 1;
}
return pxCurrentTCB;
}
/* This proof assumes that prvTCPPrepareSend and prvTCPReturnPacket are correct.
* These functions are proved to be correct separately. */
BaseType_t publicTCPHandleState( FreeRTOS_Socket_t * pxSocket,
NetworkBufferDescriptor_t ** ppxNetworkBuffer );
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
size_t socketSize = sizeof( FreeRTOS_Socket_t );
if( ensure_memory_is_valid( pxSocket, socketSize ) )
{
/* ucOptionLength is the number of valid bytes in ulOptionsData[].
* ulOptionsData[] is initialized as uint32_t ulOptionsData[ipSIZE_TCP_OPTIONS/sizeof(uint32_t)].
* This assumption is required for a memcpy function that copies uxOptionsLength
* data from pxTCPHeader->ucOptdata to pxTCPWindow->ulOptionsData.*/
__CPROVER_assume( pxSocket->u.xTCP.xTCPWindow.ucOptionLength == sizeof( uint32_t ) * ipSIZE_TCP_OPTIONS / sizeof( uint32_t ) );
/* uxRxWinSize is initialized as size_t. This assumption is required to terminate `while(uxWinSize > 0xfffful)` loop.*/
__CPROVER_assume( pxSocket->u.xTCP.uxRxWinSize >= 0 && pxSocket->u.xTCP.uxRxWinSize <= sizeof( size_t ) );
/* uxRxWinSize is initialized as uint16_t. This assumption is required to terminate `while(uxWinSize > 0xfffful)` loop.*/
__CPROVER_assume( pxSocket->u.xTCP.usMSS == sizeof( uint16_t ) );
if( xIsCallingFromIPTask() == pdFALSE )
{
__CPROVER_assume( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED );
__CPROVER_assume( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED );
}
}
NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
size_t bufferSize = sizeof( NetworkBufferDescriptor_t );
if( ensure_memory_is_valid( pxNetworkBuffer, bufferSize ) )
{
pxNetworkBuffer->pucEthernetBuffer = safeMalloc( sizeof( TCPPacket_t ) );
}
if( ensure_memory_is_valid( pxSocket, socketSize ) &&
ensure_memory_is_valid( pxNetworkBuffer, bufferSize ) &&
ensure_memory_is_valid( pxNetworkBuffer->pucEthernetBuffer, sizeof( TCPPacket_t ) ) &&
ensure_memory_is_valid( pxSocket->u.xTCP.pxPeerSocket, socketSize ) )
{
publicTCPHandleState( pxSocket, &pxNetworkBuffer );
}
}

View File

@ -0,0 +1,50 @@
#
# FreeRTOS memory safety proofs with CBMC.
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://aws.amazon.com/freertos
# http://www.FreeRTOS.org
#
{
"ENTRY": "TCPPrepareSend",
"CBMCFLAGS":
[
"--unwind 1",
"--nondet-static"
],
"OBJS":
[
"$(ENTRY)_harness.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto"
],
"DEF":
[
"FREERTOS_TCP_ENABLE_VERIFICATION"
],
"INC":
[
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
]
}

View File

@ -0,0 +1,15 @@
This is the memory safety proof for prvTCPPrepareSend.
This proof is a work-in-progress. Proof assumptions are described in
the harness. The proof also assumes the following functions are
memory safe and have no side effects relevant to the memory safety of
this function:
* ulTCPWindowTxGet
* xTCPWindowTxDone
* xTaskGetTickCount
* uxStreamBufferGet
* vReleaseNetworkBufferAndDescriptor
* vSocketWakeUpUser

View File

@ -0,0 +1,88 @@
/*
* FreeRTOS memory safety proofs with CBMC.
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_Stream_Buffer.h"
#include "../../utility/memory_assignments.c"
/* This proof assumes that pxGetNetworkBufferWithDescriptor is implemented correctly. */
int32_t publicTCPPrepareSend( FreeRTOS_Socket_t * pxSocket,
NetworkBufferDescriptor_t ** ppxNetworkBuffer,
UBaseType_t uxOptionsLength );
/* Abstraction of pxGetNetworkBufferWithDescriptor. It creates a buffer. */
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t * pxBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
size_t bufferSize = sizeof( NetworkBufferDescriptor_t );
if( ensure_memory_is_valid( pxBuffer, bufferSize ) )
{
/* The code does not expect pucEthernetBuffer to be equal to NULL if
* pxBuffer is not NULL. */
pxBuffer->pucEthernetBuffer = malloc( xRequestedSizeBytes );
__CPROVER_assume( pxBuffer->pucEthernetBuffer != NULL );
pxBuffer->xDataLength = xRequestedSizeBytes;
}
return pxBuffer;
}
void harness()
{
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
size_t socketSize = sizeof( FreeRTOS_Socket_t );
size_t bufferSize = sizeof( TCPPacket_t );
if( ensure_memory_is_valid( pxNetworkBuffer, sizeof( *pxNetworkBuffer ) ) )
{
pxNetworkBuffer->xDataLength = bufferSize;
/* The code does not expect pucEthernetBuffer to be equal to NULL if
* pxNetworkBuffer is not NULL. */
pxNetworkBuffer->pucEthernetBuffer = malloc( bufferSize );
__CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL );
}
UBaseType_t uxOptionsLength;
if( pxSocket )
{
publicTCPPrepareSend( pxSocket, &pxNetworkBuffer, uxOptionsLength );
}
}

Some files were not shown because too many files have changed in this diff Show More