Developing secured embedded applications using Intel® System Studio

Intended audience: - This article speaks about using the Static Analysis feature to avoid minor errors which may lead to security vulnerabilities.

Purpose: - Embedded applications have a wide scope in various streams like Military, Aerospace and many more, where security is at most importance. So we should be able to firewall these attacks from static and dynamic vulnerabilities. So in order to catch these security vulnerabilities, we may need to inspect the code carefully.

However manually inspecting source code is important, but it is labor intensive and error prone. Source code audits can be supplemented by static and dynamic analysis tools that scan source code for security flaws. Intel® System Studio tools has functionalities to identify static and dynamic coding errors. This article will help you to understand common coding issues in embedded applications and how to write better secure code.

Intel® System Studio:-

Intel® System Studio a new comprehensive integrated tool suite provides developers with advanced system tools and technologies that help accelerate the delivery of the next generation power efficient, high performance, and reliable embedded and mobile devices.

To get more information about Intel® System Studio  http://software.intel.com/en-us/intel-system-studio

Benefits of using Intel® static analysis : - Intel® Static Analysis tool is capable of detecting around 250 different types of error conditions and  can also detect race conditions resulting from misuse of parallel programming frameworks such as OpenMP* and Intel® Cilk™ Plus.

Solution:- We have two types of profiling, with which we can attain benefit in terms of Security , Those are

  1. Static analysis
  2. Dynamic analysis

We would be discussing about static analysis in this article. Intel® Static analysis attempts to identify errors and security weaknesses through deep analysis of source code. Since many security weaknesses are also bugs, Intel® Static analysis provides an effective way to discover defects, especially in code that is hard to exercise thoroughly with tests.

Intel® Static analysis can be enabled with Intel® C++ compilers using the Compiler option "-diag-enable sc [n]"

Option

Description

-diag-enable sc{[1|2|3]}

Enables static analysis. The number specifies the severity level of diagnostics reported (1=only critical errors, 2=all errors and warnings, and 3=all diagnostics regardless of severity level).

-diag-enable sc-{full|concise|precise}

Enables static analysis and determines the analysis mode.

-diag-disable sc

Disables static analysis

-diag-enable sc-include

Analyzes system include files as well as source files. By default, apparent errors in system include files are not reported.

 System include files are those include files found using the INCLUDE environment variable.

-diag-enable sc-single-file

Processes each file individually, skipping the usual whole-program analysis. This reduces memory requirements and analysis time on large programs, but may detect fewer real errors.

-diag-sc-dir dir

Directs diagnostic results to the given directory. If this option is not specified, or if the option is specified without indicating a directory, results are directed to the current working directory. Each run creates results in a new subdirectory whose name has the form "r@@@sc", where "@@@" is replaced the next available sequence number (001, 002, ...).

This option requires that you also specify the compiler option to enable static analysis.

-diag-enable sc-enums

Instructs static analysis to treat enumeration variables as known values equal to any one of the associated enumeration literals. By default, static analysis treats unknown enumeration variables as unknown integer values. Setting this option may find additional errors, but tends to create more false positives

How to start working with Intel® Static analysis?

 Intel® Static analysis can be enabled easily with much less overhead by a single compiler option "-diag-enable sc <options>".

Let's take a simple example:-

 	#include <stdio.h>
 	#include <stdlib.h>
 	int main()
 	{
 	      int *p=(*int)malloc(5*sizeof(int));
 	      if(p==NULL)
 	      {
 	            printf(“Memory allocation is unsuccessful n”);
	      }
 	      else
 	      {
 	            p[3]=5;
 	            p[4]=6;
	      }
 	       
 	      printf(“The elements entered are %d and %d”,p[3],p[4]);
 	      return 0;
 	}

Now, we can run the above program with the following option:-

"icc -diag-enable sc3 sample1.c"

Now the compiler would produce a result file which can be opened using Intel® Inspector tool.

Likewise we can detect many such errors and I have listed some of them below:-

Problem

Description

Argument count mismatch

The number of actual arguments does not match the number of formal parameters at a call.

Argument is not a pointer

The type of an actual argument does not match the corresponding formal parameter at a subroutine call.

Attempt to violate exception specification

An exception can be thrown that violates the exception specification.

Bad format flags

Flags in a format specifier are repeated or ignored.

Base class has non-virtual destructor

 A C++ class containing virtual member functions has a non-virtual destructor.

Base class lacks destructor

A class defines virtual member functions but does not define any destructor.

Big parameter passed by value

A parameter is passed in an inefficient manner.

Bounds violation

An attempt to access outside the bounds of a variable (usually an array) was found.

Buffer overflow through pointer

 A memory write through a pointer creates a buffer overflow.

C library routine violates C++ object semantics

Routines like longjmp and exit should not be used in C++ programs.

Class has virtual member functions but no derived classes

A class has virtual member functions, but no other class is derived from that class.

Data race from cilk_for

The data usage pattern in a cilk_for loop creates a data race.

Data race from cilk_spawn

The data usage pattern in a cilk_spawn creates a data race.

Destructor contains non-empty exception specification

A C++ destructor was declared with a non-empty exception specification.

Divide by zero

An expression may divide by zero.

 We can find more information about these problem types with illustrations for each of these here :-

http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/sa-ptr/sa-ptr_win_lin/index.htm

How to open the result file using Intel® Inspector ?

 Open an another terminal and change the directory to the Installation path of Intel® system studio tools

Please follow the following article to know more about "How to use Intel® Inspector"

http://software.intel.com/en-us/articles/how-to-use-intelr-inspector-2013-for-systems

Now use the "./inspxe-gui" binary to open the results on your Linux* host and pass the result file as an argument for this binary. Now the result is opened in an Inspector GUI as shown below:-

 

 

Intel® Inspector GUI would make the analysis very easy with the "Allocation site", "issue site" and so on. When we see the GUI representation of memory leak issue in the above site, we can track it easily about where we have allocated and which is the point we forgot to delete the same after use.

In the above screenshot, we could see the "Allocation site" pointing to the source code line pointing to the Dynamic allocation of memory and "Memory leak" site pointing to the source line, where we failed to delete the above allocated memory.

NOTE:- This result file can also be used in any other remote systems (where Intel® Inspector is installed) to view the results.

We can find information about the Dynamic analysis here :- http://software.intel.com/en-us/articles/memory-profiling-techniques-using-intel-system-studio

For more complete information about compiler optimizations, see our Optimization Notice.