Dereference of an unvalidated pointer via a function call

Whenever input data is accepted from the user or the outside environment, it should be validated for type, length, format, and range before it is used. Until this data is properly validated, it is said to be tainted. The SV.TAINTED family of checkers look for the use of tainted data in code.

The SV.TAINTED.CALL.DEREF checker flags code that uses tainted data in a dereference operation via a function call.

Vulnerability and risk

When a pointer input to the code is not validated properly and is used in a dereference operation, the result can be an attempt to read or write a forbidden memory region, resulting in a program crash, or unintended reading or writing of a valid memory location that can contain sensitive data such as user passwords. This results in a potential security hole that could allow an attacker to:

  • Provide unexpected values and cause a program crash
  • Read confidential data
  • Use malicious input to modify data or alter control flow
  • Cause excessive resource consumption
  • Execute arbitrary commands

Mitigation and prevention

To avoid tainted input errors:

  • understand all the potential areas in which untrusted inputs could enter your software: parameters or arguments, cookies, input read from the network, environment variables, reverse DNS lookups, query results, filenames, databases, and any external systems;
  • use a whitelist or 'known good' policy for inputs, rather than relying only on a blacklist or 'known bad' strategy;
  • make sure all relevant properties of the input are validated, including length, type of input, ranges, missing or extra inputs, syntax, and consistency;
  • if there are security checks on the client side of an applications, make sure they are duplicated on the server side;
  • if the application combines inputs from multiple sources, perform the validation after the sources have been combined

Vulnerable code example 1

1  #include <sys/ipc.h>
2  #include <sys/shm.h>
3  #include <string.h>
5  #define SHMEM_SIZE 1024
7  typedef struct  S_ {
8        int  transaction_id;
9        int* id;
10       char* str;
11  } S;
13  void  use_shared_mem_example(key_t shmem_key,  int  id) {
14        int  shmem_id = shmget(shmem_key, SHMEM_SIZE, IPC_CREAT);
15        S* s = (S*) shmat(shmem_id, NULL, 0);
16        if  (s != (S*) (-1)) {
17             *(s->id) = id;                               // dereference of untrusted pointer, flagged as SV.TAINTED.DEREF
18             strcpy (s->str,  "Sample signal string" );      // dereference of untrusted pointer via call, flagged as SV.TAINTED.CALL.DEREF
19        }
20        shmdt(( void *) s);
21  }

In the above example, a pointer to a memory shared between processes is dereferenced directly and via a function call. Klocwork flags these operations by raising the SV.TAINTED.DEREF and SV.TAINTED.CALL.DEREF defects.

At line 17: [SV.TAINTED.DEREF] Unvalidated pointer 's->id' that is received from 'shmat' at line 15 is dereferenced at line 17.
At line 18: [SV.TAINTED.CALL.DEREF] Unvalidated pointer 's->str' that is received from 'shmat' at line 15 is dereferenced via a call to 'strcpy' at line 18.

A developer of this code can be advised to either use a reliable pointer sanitation before the dereference operations, details of which are beyond this brief checker description, or refrain from dereferencing such pointers at all.

Vulnerable code example 2

1  #include <string.h>
3  typedef struct  {
4          void  *data;
5  } request_t;
7  #define MAGIC_ADDRESS ((void*)0xdeadbeef)
8  #define MAGIC_SIZE 1024
10 char* get_sensitive_data();
11 void* read_from_port() {
12      // a library function known to return pointer to untrusted data
13      // for example, read from a fixed memory location
14      return  MAGIC_ADDRESS;
15 }
17 void  unsafe_dereference() {
18      request_t* req = read_from_port();
19      char* data = get_sensitive_data();
20      memcpy(req->data, data, MAGIC_SIZE);     // unsafe dereference inside the function, flagged by SV.TAINTED.CALL.DEREF
21 }
In this example, a similar dereference of a tainted pointer req->data is performed at line 20. Klocwork issues an SV.TAINTED.CALL.DEREF warning to flag the potential security problem:
[SV.TAINTED.CALL.DEREF] Unvalidated pointer 'req->data' that is received from 'read_from_port' at line 18 is dereferenced via a call to 'memcpy' at line 20.


This checker can be extended through the Klocwork knowledge base. See Tuning C/C++ analysis for more information.