Lecture 02
Lecture 02
Verification Laboratory
Secure C Programming:
Memory Management
Lucas Cordeiro
Department of Computer Science
[email protected]
Secure C Programming
• Lucas Cordeiro (Formal Methods Group)
§ [email protected]
§ Office: 2.28
§ Office hours: 15-16 Tuesday, 14-15 Wednesday
• Textbook:
§ Algorithm Design and Applications (Chapter 2)
§ Introduction to Algorithms (Chapter 10)
§ C How to Program (Chapter 12)
https://www.zdnet.com/article/microsoft-70-percent-of-
all-security-bugs-are-memory-safety-issues/
Dereferencing NULL pointers can allow
attackers to execute code
https://www.theregister.co.uk/2009/07/17/linux_kernel_exploit/
Intended learning outcomes
• Understand risk assessment to guide software
developers
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
• Develop safe, reliable, and secure systems
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
• Develop safe, reliable, and secure systems
• Eliminate undefined behaviours that can lead
to undefined program behaviours and
exploitable vulnerabilities
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
• Develop safe, reliable, and secure systems
• Eliminate undefined behaviours that can lead
to undefined program behaviours and
exploitable vulnerabilities
Risk Assessment
• CERT C Coding Standard contains a risk
assessment section
§ Indicate the potential consequences of not addressing a
particular rule or recommendation in their code
Risk Assessment
• CERT C Coding Standard contains a risk
assessment section
§ Indicate the potential consequences of not addressing a
particular rule or recommendation in their code
• This information can be used to prioritize the repair
of rule violations by a development team
§ The metric is designed primarily for remediation projects
Risk Assessment
• CERT C Coding Standard contains a risk
assessment section
§ Indicate the potential consequences of not addressing a
particular rule or recommendation in their code
• This information can be used to prioritize the repair
of rule violations by a development team
§ The metric is designed primarily for remediation projects
• We assume that new code will be developed to be
compliant with the entire
§ coding standard
§ applicable recommendations
Severity
• How serious are the consequences of the rule
being ignored?
Value Meaning
1 Unlikely
2 Probable
3 Likelly
Remediation Cost
• How expensive is it to comply with the rule?
L2 6, 8, 9 Medium severity,
probable, medium cost
to repair
L3 1, 2, 3, 4 Low severity, unlikely,
expensive to repair
https://wiki.sei.cmu.edu/confluence/display/c/
SEI+CERT+C+Coding+Standard
Risk Assessment Summary
https://wiki.sei.cmu.edu/confluence/display/c/
SEI+CERT+C+Coding+Standard
Risk Assessment Summary
https://wiki.sei.cmu.edu/confluence/display/c/
SEI+CERT+C+Coding+Standard
Risk Assessment Summary
https://wiki.sei.cmu.edu/confluence/display/c/
SEI+CERT+C+Coding+Standard
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
• Develop safe, reliable, and secure systems
• Eliminate undefined behaviours that can lead
to undefined program behaviours and
exploitable vulnerabilities
Dynamic data structures
• Examples of fixed-size data structures include
single-subscripted arrays, double-
subscripted arrays and structs
typedef struct account {
unsigned short age;
char name[100];
} accountt;
int main()
{
int x[3];
int a[3][4];
accountt acount;
return 0;
}
Dynamic data structures
• Examples of fixed-size data structures include
single-subscripted arrays, double-
subscripted arrays and structs
• Dynamic data structures
§ They can grow and shrink during execution
Dynamic data structures
• Examples of fixed-size data structures include
single-subscripted arrays, double-
subscripted arrays and structs
• Dynamic data structures
§ They can grow and shrink during execution
• Linked lists
§ Allow insertions and removals anywhere in a
linked list
15 5 10
head
Self-referential structures
• Self-referential structures
§ Structure that contains a pointer to a structure of the
same type
Self-referential structures
• Self-referential structures
§ Structure that contains a pointer to a structure of the
same type
§ Terminated with a NULL pointer (0)
typedef struct node {
int data;
struct node *nextPtr;
} nodet;
Self-referential structures
• Self-referential structures
§ Structure that contains a pointer to a structure of the
same type
§ Terminated with a NULL pointer (0)
typedef struct node {
int data; Not setting the link in the last
struct node *nextPtr; node of a list to NULL can
} nodet; lead to runtime errors
§ nextPtr
o Points to an object of type node
o Referred to as a link
o Ties one node to another node
Self-referential structures
• Self-referential structures
§ Structure that contains a pointer to a structure of the
same type
§ Terminated with a NULL pointer (0)
typedef struct node {
int data; Not setting the link in the last
struct node *nextPtr; node of a list to NULL can
} nodet; lead to runtime errors
§ nextPtr
o Points to an object of type node
o Referred to as a link
o Ties one node to another node
§ Can be linked together to form useful data structures
such as lists, queues, stacks and trees
Dynamic memory allocation
• Dynamic memory allocation
§ Obtain and release memory during execution
Dynamic memory allocation
• Dynamic memory allocation
§ Obtain and release memory during execution
• malloc
§ Takes number of bytes to allocate
o Use sizeof to determine the size of an object
§ Returns pointer of type void *
o A void * pointer may be assigned to any pointer
o If no memory available, returns NULL
§ Example: nodet *newPtr = (nodet *)malloc(sizeof(nodet));
Dynamic memory allocation
• Dynamic memory allocation
§ Obtain and release memory during execution
• malloc
§ Takes number of bytes to allocate
o Use sizeof to determine the size of an object
§ Returns pointer of type void *
o A void * pointer may be assigned to any pointer
o If no memory available, returns NULL
§ Example: nodet *newPtr = (nodet *)malloc(sizeof(nodet));
• free
§ Always deallocates memory allocated by malloc to
avoid memory leak
§ Takes a pointer as an argument
o free (newPtr);
Dynamic memory allocation
Two self-referential structures linked together
15 10
int main() {
// allocates memory
nodet *node1 = (nodet *)malloc(sizeof(nodet));
nodet *node2 = (nodet *)malloc(sizeof(nodet));
node1->data = 15;
node2->data = 10;
// link node1 to node2
node1->nextPtr = node2;
node2->nextPtr = NULL;
// Deallocates memory allocated by malloc
free(node1);
free(node2);
return 0;
}
Dynamic memory allocation
Two self-referential structures linked together
15 10
int main() {
// allocates memory
nodet *node1 = (nodet *)malloc(sizeof(nodet));
nodet *node2 = (nodet *)malloc(sizeof(nodet));
node1->data = 15;
node2->data = 10; If there exists no memory
// link node1 to node2 available, then malloc
node1->nextPtr = node2; returns NULL
node2->nextPtr = NULL;
// Deallocates memory allocated by malloc
free(node1);
free(node2);
return 0;
}
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
15 5 10
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
§ Connected by pointer links
15 5 10
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
§ Connected by pointer links
§ Accessed via a pointer to the first node of the list
head
15 5 10
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
§ Connected by pointer links
§ Accessed via a pointer to the first node of the list
§ Subsequent nodes are accessed via the link-pointer
member of the current node
head currentPtr
15 5 10
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
§ Connected by pointer links
§ Accessed via a pointer to the first node of the list
§ Subsequent nodes are accessed via the link-pointer
member of the current node
§ Link pointer in the last node is set to NULL to mark the
list’s end
head currentPtr
15 5 10
Linked lists properties
• Linked list
§ Linear collection of self-referential class objects,
called nodes
§ Connected by pointer links
§ Accessed via a pointer to the first node of the list
§ Subsequent nodes are accessed via the link-pointer
member of the current node
§ Link pointer in the last node is set to NULL to mark the
list’s end
• Use a linked list instead of an array when
§ You have an unpredictable number of elements
§ Your list needs to be sorted quickly
Linked lists properties
• Linked lists are dynamic, so the length of a list
can increase or decrease as necessary
Linked lists properties
• Linked lists are dynamic, so the length of a list
can increase or decrease as necessary
• Can we change the array size after compiling the
program? What are the problems here?
Linked lists properties
• Linked lists are dynamic, so the length of a list
can increase or decrease as necessary
• Can we change the array size after compiling the
program? What are the problems here?
§ Arrays can become full
o An array can be declared to contain more elements than the
number of data items expected, but this can waste memory
Linked lists properties
• Linked lists are dynamic, so the length of a list
can increase or decrease as necessary
• Can we change the array size after compiling the
program? What are the problems here?
§ Arrays can become full
o An array can be declared to contain more elements than the
number of data items expected, but this can waste memory
15 10 … 18
int main() {
…
// link the nodes
startPtr = node1;
node1->nextPtr = node2;
node2->nextPtr = node3;
node3->nextPtr = NULL;
…
return 0;
}
A graphical representation of a
linked list
startPtr
15 10 … 18
int main() {
… Pointers should be initialised
// link the nodes before they’re used
startPtr = node1;
node1->nextPtr = node2;
node2->nextPtr = node3;
node3->nextPtr = NULL;
…
return 0;
}
A graphical representation of a
linked list
startPtr
15 10 … 18
int main() {
… Pointers should be initialised
// link the nodes before they’re used
startPtr = node1;
node1->nextPtr = node2; A structure’s size is not
node2->nextPtr = node3; necessarily the sum of the size
node3->nextPtr = NULL; of its members (machine-
… dependent boundary
return 0;
alignment)
}
Error prevention when using
linked lists
• If dynamically allocated memory is no longer
needed, use free to return it to the system
§ Why must we set that pointer to NULL?
Error prevention when using
linked lists
• If dynamically allocated memory is no longer
needed, use free to return it to the system
§ Why must we set that pointer to NULL?
o eliminate the possibility that the program could refer to
memory that’s been reclaimed and which may have already
been allocated for another purpose
Error prevention when using
linked lists
• If dynamically allocated memory is no longer
needed, use free to return it to the system
§ Why must we set that pointer to NULL?
o eliminate the possibility that the program could refer to
memory that’s been reclaimed and which may have already
been allocated for another purpose
find an object
remove first element
remove last element
remove at given index
size
O(1)
O(1)
O(1)
O(1)
O(n)
size O(1)
Intended learning outcomes
• Understand risk assessment to guide software
developers
• Review dynamic data structures (linked list)
• Provide rules for secure coding in the C
programming language
• Develop safe, reliable, and secure systems
• Eliminate undefined behaviours that can lead
to undefined program behaviours and
exploitable vulnerabilities
Do not access freed memory
(MEM30-C)
• Evaluating a pointer into memory that has been
deallocated by a memory management function is
undefined behaviour
Do not access freed memory
(MEM30-C)
• Evaluating a pointer into memory that has been
deallocated by a memory management function is
undefined behaviour
• Pointers to memory that has been deallocated are
called dangling pointers
§ Accessing a dangling pointer can result in exploitable
vulnerabilities
Do not access freed memory
(MEM30-C)
• Evaluating a pointer into memory that has been
deallocated by a memory management function is
undefined behaviour
• Pointers to memory that has been deallocated are
called dangling pointers
§ Accessing a dangling pointer can result in exploitable
vulnerabilities
• Using the value of a pointer that refers to space
deallocated by a call to the free() or realloc()
function is undefined behaviour
Noncompliant Code Example
• Illustrates the incorrect technique for freeing the
memory associated with a linked list
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
void free_list(struct node *head) {
for (struct node *p = head; p != NULL; p
= p->next) {
free(p);
}
}
Compliant Solution
• p is freed before p->next is executed, so that p->next
reads memory that has already been freed
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
void free_list(struct node *head) {
struct node *q;
for(struct node *p=head; p!=NULL; p=q) {
q = p->next;
free(p);
}
}
Risk Assessment
• Reading memory that has been freed can lead to
§ abnormal program termination
§ denial-of-service attacks
Risk Assessment
• Reading memory that has been freed can lead to
§ abnormal program termination
§ denial-of-service attacks
• Writing memory that has already been freed can
lead to the execution of arbitrary code
Risk Assessment
• Reading memory that has been freed can lead to
§ abnormal program termination
§ denial-of-service attacks
• Writing memory that has already been freed can
lead to the execution of arbitrary code
• Reading a pointer to deallocated memory is
undefined behaviour
§ the pointer value is indeterminate and might be a trap
representation
Risk Assessment
• Reading memory that has been freed can lead to
§ abnormal program termination
§ denial-of-service attacks
• Writing memory that has already been freed can
lead to the execution of arbitrary code
• Reading a pointer to deallocated memory is
undefined behaviour
§ the pointer value is indeterminate and might be a trap
representation
#include <stdlib.h>
enum { BUFFER_SIZE = 32 };
int f(void) {
char *text_buffer=(char *)malloc(BUFFER_SIZE);
if (text_buffer == NULL) {
return -1;
}
free(text_buffer);
return 0;
}
Risk Assessment
• Failing to free memory can result in
§ Exhaustion of system memory resources
§ Denial-of-service attack
Risk Assessment
• Failing to free memory can result in
§ Exhaustion of system memory resources
§ Denial-of-service attack
if (flex_struct == NULL) {
/* Handle error */
}
/* Initialize structure */
flex_struct->num = array_size;
#include <stdlib.h>
void f(void) {
char buf[BUFSIZE];
char *p = (char *)realloc(buf, 2 * BUFSIZE);
if (p == NULL) {
/* Handle error */
}
}
Compliant Solution
• In this compliant solution, buf refers to dynamically
allocated memory:
#include <stdlib.h>
void f(void) {
char *buf = (char *)malloc(BUFSIZE * sizeof(char));
char *p = (char *)realloc(buf, 2 * BUFSIZE);
if (p == NULL) {
/* Handle error */
}
}
Risk Assessment
• The consequences of this error depend on the
implementation
§ they range from nothing to arbitrary code execution if
that memory is reused by malloc()
Risk Assessment
• The consequences of this error depend on the
implementation
§ they range from nothing to arbitrary code execution if
that memory is reused by malloc()
After realloc():
ptr1 = 0x1621a010