Skip to content

Implement C Declarations7 package #165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
"Declarations4",
"Declarations5",
"Declarations6",
"Declarations7",
"Exceptions1",
"Exceptions2",
"Expressions",
Expand Down
292 changes: 292 additions & 0 deletions c/cert/src/rules/DCL39-C/InformationLeakageAcrossTrustBoundariesC.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @id c/cert/information-leakage-across-trust-boundaries-c
* @name DCL39-C: Avoid information leakage when passing a structure across a trust boundary
* @description Passing a structure with uninitialized fields or padding bytes can cause information
* to be unintentionally leaked.
* @kind problem
* @precision medium
* @problem.severity error
* @tags external/cert/id/dcl39-c
* security
* external/cert/obligation/rule
*/

import cpp
import codingstandards.c.cert
import codingstandards.cpp.rules.informationleakageacrossboundaries.InformationLeakageAcrossBoundaries

class InformationLeakageAcrossTrustBoundariesCQuery extends InformationLeakageAcrossBoundariesSharedQuery {
InformationLeakageAcrossTrustBoundariesCQuery() {
this = Declarations7Package::informationLeakageAcrossTrustBoundariesCQuery()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
| arrays.c:11:20:11:21 | wa | 'wa' may leak information from {elements of a[...] (arrays.c:7)}. Path: wa (arrays.c:11) --> & ... (arrays.c:12) |
| arrays.c:33:22:33:23 | wa | 'wa' may leak information from {elements of elements of a[...][...] (arrays.c:29)}. Path: wa (arrays.c:33) --> & ... (arrays.c:34) |
| arrays.c:57:22:57:23 | wa | 'wa' may leak information from {WithPointer (arrays.c:52)}. Path: wa (arrays.c:57) --> & ... (arrays.c:59) |
| interprocedural.c:37:9:37:9 | p | 'p' may leak information from {y (interprocedural.c:8)}. Path: p (interprocedural.c:37) --> past assign_x (interprocedural.c:32) --> & ... (interprocedural.c:39) |
| interprocedural.c:104:9:104:9 | p | 'p' may leak information from {x (interprocedural.c:7), y (interprocedural.c:8)}. Path: p (interprocedural.c:104) --> overwrite_after_leak(...) (interprocedural.c:96) --> p (interprocedural.c:97) |
| multilayer.c:16:10:16:10 | s | 's' may leak information from {b (multilayer.c:12)}. Path: s (multilayer.c:16) --> & ... (multilayer.c:18) |
| multilayer.c:29:10:29:10 | s | 's' may leak information from {b (multilayer.c:12), x (multilayer.c:7)}. Path: s (multilayer.c:29) --> & ... (multilayer.c:30) |
| multilayer.c:34:8:34:8 | s | 's' may leak information from {struct <unnamed> (multilayer.c:6)}. Path: s (multilayer.c:34) --> & ... (multilayer.c:35) |
| test.c:12:12:12:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:12) --> & ... (test.c:14) |
| test.c:18:12:18:12 | s | 's' may leak information from {x (test.c:7)}. Path: s (test.c:18) --> & ... (test.c:20) |
| test.c:24:12:24:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:24) --> & ... (test.c:25) |
| test.c:36:12:36:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:36) --> & ... (test.c:38) |
| test.c:43:12:43:12 | s | 's' may leak information from {x (test.c:7)}. Path: s (test.c:43) --> & ... (test.c:47) |
| test.c:58:12:58:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:58) --> & ... (test.c:59) |
| test.c:64:12:64:12 | s | 's' may leak information from {y (test.c:8)}. Path: s (test.c:64) --> & ... (test.c:66) |
| test.c:112:16:112:16 | s | 's' may leak information from {buf (test.c:92)}. Path: s (test.c:112) --> & ... (test.c:115) |
| test.c:128:12:128:12 | s | 's' may leak information from {x (test.c:7), y (test.c:8)}. Path: s (test.c:128) --> & ... (test.c:132) |
| test.c:157:22:157:22 | s | 's' may leak information from {2 to 2 bytes of padding in has_padding (test.c:151)}. Path: s (test.c:157) --> & ... (test.c:160) |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// GENERATED FILE - DO NOT MODIFY
import codingstandards.cpp.rules.informationleakageacrossboundaries.InformationLeakageAcrossBoundaries
62 changes: 62 additions & 0 deletions c/common/test/rules/informationleakageacrossboundaries/arrays.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <stddef.h>
#include <string.h>

unsigned long copy_to_user(void *to, const void *from, unsigned long n);

struct WithArray {
int a[2];
};

void forget_array() {
struct WithArray wa;
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
}

void write_partial_array() {
struct WithArray wa;
wa.a[0] = 1;
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT[FALSE NEGATIVE]
}

void write_full_array() {
struct WithArray wa;
wa.a[0] = 1;
wa.a[1] = 1;
copy_to_user(0, &wa, sizeof wa); // COMPLIANT
}

struct WithArray2D {
int a[2][1];
};

void forget_array2d() {
struct WithArray2D wa;
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
}

void write_partial_array2d() {
struct WithArray2D wa;
wa.a[0][0] = 1;
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT[FALSE NEGATIVE]
}

void write_full_array2d() {
struct WithArray2D wa;
wa.a[0][0] = 1;
wa.a[1][0] = 1;
copy_to_user(0, &wa, sizeof wa); // COMPLIANT
}

// A pointer field allows mostly the same syntactic operations as an array
// field, but the semantics are completely different.
struct WithPointer {
int *a;
};

void pointer_array_expression() {
struct WithPointer wa;
wa.a[0] = 1;
copy_to_user(0, &wa, sizeof wa); // NON_COMPLIANT
}

// TODO: test a struct in an array
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <stddef.h>
#include <string.h>

unsigned long copy_to_user(void *to, const void *from, unsigned long n);

typedef struct _point {
int x;
int y;
} point;

void callee1(point *p) {
p->y = 1;
copy_to_user(0, p, sizeof(point)); // COMPLIANT
}

void caller1() {
point p;
p.x = 1;
callee1(&p);
}

void callee2(point *p) {
memset(p, 0, sizeof(point));
copy_to_user(0, p, sizeof(point)); // COMPLIANT
}

void caller2() {
point p;
callee2(&p);
}

void assign_x(point *p, int value) { p->x = value; }

void zero_y(point *p) { memset(&p->y, 0, sizeof(p->y)); }

void call_to_overwrite_x() {
point p;
assign_x(&p, 1);
copy_to_user(0, &p, sizeof p); // NON_COMPLIANT
}

void call_to_overwrite_both() {
point p;
assign_x(&p, 1);
zero_y(&p);
copy_to_user(0, &p, sizeof p); // COMPLIANT
}

void zero_y_and_loop(point *p) {
int i;
memset(&p->y, 0, sizeof(p->y));
for (i = 0; i < 10; i++) {
p->y++;
}
}

void call_zero_y_and_loop() {
point p;
zero_y_and_loop(&p);
assign_x(&p, 1);
copy_to_user(0, &p, sizeof p); // COMPLIANT
}

int zero_y_or_fail(point *p) {
if (p->x < 0) {
return 0;
}
p->y = 0;
return 1;
}

void call_zero_y_or_fail(int i) {
point p;
p.x = i;
if (!zero_y_or_fail(&p)) {
return;
}
copy_to_user(0, &p, sizeof p); // COMPLIANT
}

int zero_y_proxy(point *p) {
if (p->x) {
zero_y(p);
} else {
zero_y(p);
}
}

void call_zero_y_proxy() {
point p;
zero_y_proxy(&p);
assign_x(&p, 1);
copy_to_user(0, &p, sizeof p); // COMPLIANT
}

void overwrite_after_leak(point *p) {
copy_to_user(0, p, sizeof(*p)); // NON_COMPLIANT

p->x = 0;
p->y = 0;
}

void call_overwrite_after_leak(void) {
point p;
overwrite_after_leak(&p);
copy_to_user(0, &p, sizeof p); // COMPLIANT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <stddef.h>
#include <string.h>

unsigned long copy_to_user(void *to, const void *from, unsigned long n);

typedef struct {
int x;
} intx;

typedef struct {
intx a;
intx b;
} intxab;

void forget_y() {
intxab s;
s.a.x = 1;
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (y)
}

void set_both() {
intxab s;
s.a.x = 1;
memset(&s.b, 0, sizeof s.b);
copy_to_user(0, &s, sizeof s); // COMPLIANT
}

void set_none() {
intxab s;
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (both)
}

void set_none_intx() {
intx s;
copy_to_user(0, &s, sizeof s); // NON_COMPLIANT (x)
}
Loading