Writing Coverity model: pointer in struct ALWAYS points to tainted data - code-analysis

I reguarly check lwIP, a free TCP/IP stack with Coverity.
As a network stack, we have untrusted data coming in from the network which is stored in struct pbuf (some members omitted for clarity):
struct pbuf {
void *payload;
u16_t len;
u16_t ref;
};
My questions are:
1) I want to model that "void* payload" of struct pbuf ALWAYS points to tainted data, every access to it must be untrusted. How can I do this?
2) We use refcounting (u16_t ref). Is there any way to model refcounting in Coverity?

Related

Can't access the memory which was malloc() in DLL

Dear,
Recently I run into a general issue, I am writing a DLL, which will be used/invoked by another program. It has structure like this :
DLLEXT long AMI_Init(void **AMI_dll_memory)
{
mem = (struct model_memory*)malloc(sizeof(struct model_memory));
mem->submem = (struct submem*)malloc(sizeof(struct submem));
......
*AMI_dll_memory = (void*)mem;
}
DLLEXT long AMI_Get(void *AMI_dll_memory)
{
....
mem = (struct model_memory*)AMI_dll_memory;
mem->submem->init();
}
// Defined in submem module
struct {
int data;
struct list* next;
}list;
void init()
{
struct list* n;
n = (struct list*)malloc(sizeof(struct list));
// access n->data caused memory access violation.
}
Another software will invoke the AMI_Init() first, then call AMI_Get() with passing the AMI_dll_memory in between, but I got access violation once I tried to access the data "n->data" of "mem->submem->init()". Why it is ? I confirmed I can apply memory since the malloc funtion returned successfully, but just can't access n->data, anyone know why it is ? n->data didn't belong to current process after memory passing in funtions ? Thanks so much.
Guys,
I figure out what is going on here, it is related to implicit declaration of malloc() function, when I malloc memory in second places, I didn't include stdlib.h in that file, which caused the issue.

fatfs f_write returns FR_DISK_ERR when passing a pointer to data in a mail queue

I'm trying to use FreeRTOS to write ADC data to SD card on the STM32F7 and I'm using V1 of the CMSIS-RTOS API. I'm using mail queues and I have a struct that holds an array.
typedef struct
{
uint16_t data[2048];
} ADC_DATA;
on the ADC half/Full complete interrupts, I add the data to the queue and I have a consumer task that writes this data to the sd card. My issue is in my Consumer Task, I have to do a memcpy to another array and then write the contents of that array to the sd card.
void vConsumer(void const * argument)
{
ADC_DATA *rx_data;
for(;;)
{
writeEvent = osMailGet(adcDataMailId, osWaitForever);
if(writeEvent.status == osEventMail)
{
// write Data to SD
rx_data = writeEvent.value.p;
memcpy(sd_buff, rx_data->data, sizeof(sd_buff));
if(wav_write_result == FR_OK)
{
if( f_write(&wavFile, (uint8_t *)sd_buff, SD_WRITE_BUF_SIZE, (void*)&bytes_written) == FR_OK)
{
file_size+=bytes_written;
}
}
osMailFree(adcDataMailId, rx_data);
}
}
This works as intended but if I try to change this line to
f_write(&wavFile, (uint8_t *)rx_data->data, SD_WRITE_BUF_SIZE, (void*)&bytes_written) == FR_OK)
so as to get rid of the memcpy, f_write returns FR_DISK_ERR. Can anyone help shine a light on why this happens, I feel like the extra memcpy is useless and you should just be able to pass the pointer to the queue straight to f_write.
So just a few thoughts here:
memcpy
Usually I copy only the necessary amount of data. If I have the size of the actual data I'll add a boundary check and pass it to memcpy.
Your problem
I am just guessing here, but if you check the struct definition, the data field has the type uint16_t and you cast it to a byte pointer. Also the FatFs documentation expects a void* for the type of buf.
EDIT: Could you post more details of sd_buff

printf implementation for embedded system

where can I find an almost complete implementation (float, width, etc.) suitable for embedded systems (few nested funtction call, low stack and ram usage, no heap, mo syscall)
Have you checked out ChibiOS's implementation of chvprintf? It's Apache-licensed and float-support (costly) is a compile-time option via define.
It's built with microcontrollers in mind. The macros are all pretty much only calls to a function pointer in the supplied BaseSequentialStream struct and you can replace them as you see fit. The var-args list is your regular stdarg.h implementation.
For transmitting on the serial port, the quickest thing is:
int32_t printfDebugSerial(const char *format, ...)
{
if (strlen(format) >200) return -1;
char tempBuff[256]; memset(tempBuff, 0, sizeof tempBuff);
va_list arg;
int32_t done;
va_start (arg, format);
done = (int32_t)vsprintf(tempBuff,format, arg);
va_end (arg);
pushMsgOnSerial((uint8_t*)tempBuff, done);
return done;
}
where pushMsgOnSerial() will be your board specific function for sending bytes on the serial port.

Passing a 32-bit struct into an 32-bit integer function argument

I have some straight C code in my Objective-C project. In one of the APIs I'm using, I can register for a callback with a function that takes an 32-bit integer parameter:
void Callback(Packet* packet, int32_t port);
I want to be able to send my callback two 16-bit ports instead of one 32-bit port. Naturally, I could just use bitwise operations, but I'd prefer something more explicit.
Here's my current solution with a union:
typedef struct {
int16_t port1;
int16_t port2;
} MultiPortStruct;
typedef union {
int32_t port;
MultiPortStruct portStruct;
} MultiPortAdaptor;
In the sender:
void registerCallback(int16_t port1, int16_t port2) {
MultiPortAdaptor adaptor;
adaptor.portStruct.port1 = port1;
adaptor.portStruct.port2 = port2;
int32_t port = adaptor.port
RegisterAPICallback(&myCallback, port);
}
In the callback:
void myCallback(Packet* packet, int32_t port) {
MultiPortAdaptor adaptor;
adaptor.port = port;
int16_t port1 = adaptor.portStruct.port1;
int16_t port2 = adaptor.portStruct.port2;
// do stuff
}
Is this approach correct or are there problems with it? (For example: should I zero out the adaptor unions? Is it OK to access different members of the same union?) Is there a simpler way?
UPDATE:
OK, I'm convinced: even if doing this is possible, it's probably not a great idea. I've decided to simply use a set of functions to do the bitwise operations for me:
int32_t SubPortsToPort(int16_t port1, int16_t port2)
int16_t PortToSubPort1(int32_t port)
int16_t PortToSubPort2(int32_t port)
So now all I have to do is this:
void registerCallback(int16_t port1, int16_t port2) {
int32_t port = SubPortsToPort(port1, port2);
RegisterAPICallback(&myCallback, port);
}
And in the callback:
void myCallback(Packet* packet, int32_t port) {
int16_t port1 = PortToSubPort1(port);
int16_t port2 = PortToSubPort2(port);
// do stuff
}
Less code, less worries!
First it is OK to store into one member and read from another member of the same union provided you only read bytes you have written - any others have unspecified values.
The issue with what you are doing is the possible introduction by the compiler of padding between fields, which would destroy your carefully arranged overlap. With current compilers & cpu architectures you will probably be OK, but there is no need to leave it to chance as there are a number of ways to fix the alignment of fields.
The simplest, though compiler dependent, method is to use the packed attribute:
typedef struct __attribute((packed))
{
int16_t port1;
int16_t port2;
} MultiPortStruct;
This simply instructs the compiler not to add any padding, so the above will always be 32-bits even on architectures which use, say, 4-byte alignment for 2-byte values.
This attribute is supported by Clang, GCC & LLVM (maybe not all versions?) - the compiler will tell you if it doesn't. If you are using a compiler which does not support the attribute (or an equivalent one) then you can look into using the C language _Alignof and _Alignas features.
HTH
With the "struct in a union trick" you have to take care, because the structure members can be padded:
There may be unnamed padding within a structure object, but not at its
beginning.
ISO/IEC 9899:TC3, 6.7.2.1 – 13
Therefore, …
typedef struct {
int16_t port1;
int16_t port2;
} MultiPortStruct;
… can have a layout as …
typedef struct {
int32_t port1;
int32_t port2;
} MultiPortStruct;
… if the implementation likes that.
So the overlay in the union will not work, even this is not very likely.
It would be similar with bitfields:
typedef struct {
int port1:16;
int port2:16;
} MultiPortStruct;
This is, because the compiler has to put the following bitfield into the same unit, if it fits, but can chose the unit.
An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit.
ibidem, 6.7.2.1 – 10
Therefore, it is theoretically possible, that an implementation choses int16 as allocation unit and places padding between the fields, even this makes no sense and is very unlikely.
As mentioned in the comment, there is nothing wrong with bitfields.
As others said, a struct might have padding (though unlikely). Another approach that would at least not have internal padding would be
typedef struct {
int16_t port[2];
} MultiPortStruct;
arrays never have internal padding and the first field of a struct is always at its start. Now theoretically this still could have padding at the end, so you should check with something like
_Static_assert(sizeof(MultiPortStruct)==2*sizeof(int16_t));

Getting raw bytes from packed struct

I've got a struct which looks like this:
#[repr(packed)]
struct Header {
some: u8,
thing: u8,
}
How can I get raw bytes from it, that I could use for either a C library or socket interaction?
I was hoping to use transmute to solve the problem, but unfortunately this doesn't work:
let header = Header {....}
let header_bytes: &[u8] = unsafe { mem::transmute(header) };
let result = self.socket.write(header_bytes);
This fails with
error: transmute called on types with different sizes: &Header (64 bits) to &[u8] (128 bits)
Edit: updated for Rust 1.x.
You can't transmute arbitrary thing to arbitrary thing (like Header to &[u8]) because transmute() is akin to reinterpret_cast in C++: it literally reinterprets the bytes which its argument consists of, and in order for this to be successful the source and the target type should have the same size. But even if Header and &[u8] had the same size, it wouldn't make sense to convert between them: Header is an actual value while &[u8] is a pointer with a size of data behind that pointer.
In order to interpret a piece of data as a slice of bytes you need to perform three steps: obtain a raw pointer to the data, convert it to a pointer to u8 and then convert that to a slice of u8. This means enhancing the raw pointer value with the length, which in this case is equal to the structure size. The last step can easily be done with std::slice::from_raw_parts():
use std::slice;
use std::mem;
let p: *const Header = &header; // the same operator is used as with references
let p: *const u8 = p as *const u8; // convert between pointer types
let s: &[u8] = unsafe {
slice::from_raw_parts(p, mem::size_of::<Header>())
};
However, doing this in most cases is not a good idea. Even though the struct is marked as packed, it still leaves the problem with the byte order, so at the very least the code which does this won't be portable (or rather, the data it serializes in such form may not be recoverable by the same program compiled for another architecture).
You can make any object into a byte slice with a function like this:
/// Safe to use with any wholly initialized memory `ptr`
unsafe fn raw_byte_repr<'a, T>(ptr: &'a T) -> &'a [u8]
{
std::mem::transmute(std::raw::Slice{
data: ptr as *const _ as *const u8,
len: std::mem::size_of::<T>(),
})
}
Run in Rust playpen.
I don't know the full safety analysis, but as long as you don't access any uninit values it should be fine.