Skip to content

Commit a1bc243

Browse files
committed
Implement rule SIG35-C
1 parent e7dec51 commit a1bc243

File tree

8 files changed

+96
-19
lines changed

8 files changed

+96
-19
lines changed

c/cert/src/rules/SIG30-C/CallOnlyAsyncSafeFunctionsWithinSignalHandlers.ql

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@ import codingstandards.c.Signal
1717
import semmle.code.cpp.dataflow.DataFlow
1818

1919
/**
20-
* Does not an access an external variable except
21-
* to assign a value to a volatile static variable of sig_atomic_t type
20+
* Does not access an external variable except
21+
* to assign a value to a volatile static variable of `sig_atomic_t` type
2222
*/
2323
class AsyncSafeVariableAccess extends VariableAccess {
2424
AsyncSafeVariableAccess() {
2525
this.getTarget() instanceof StackVariable
2626
or
27-
this.getType().hasName("volatile sig_atomic_t") and // TODO search without "volatile"
28-
this.isModified() and
29-
this.getTarget().isVolatile()
27+
this.getTarget().(StaticStorageDurationVariable).getType().(SigAtomicType).isVolatile() and
28+
this.isModified()
3029
}
3130
}
3231

c/cert/src/rules/SIG31-C/DoNotAccessSharedObjectsInSignalHandlers.ql

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@ class UnsafeSharedVariableAccess extends VariableAccess {
2727
this.getTarget().isThreadLocal()
2828
) and
2929
// excluding `volatile sig_atomic_t` type
30-
not (
31-
this.getType().hasName("volatile sig_atomic_t") and // TODO search without "volatile"
32-
this.getTarget().isVolatile()
33-
) and //excluding lock-free atomic objects
30+
not this.getType().(SigAtomicType).isVolatile() and
31+
// excluding lock-free atomic objects
3432
not exists(MacroInvocation mi, VariableAccess va |
3533
mi.getMacroName() = "atomic_is_lock_free" and
3634
mi.getExpr().getChild(0) = va.getEnclosingElement*() and

c/cert/src/rules/SIG34-C/DoNotCallSignalFromInterruptibleSignalHandlers.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66
* @precision very-high
77
* @problem.severity error
88
* @tags external/cert/id/sig34-c
9+
* correctness
10+
* security
911
* external/cert/obligation/rule
1012
*/
1113

1214
import cpp
1315
import codingstandards.c.cert
1416
import codingstandards.c.Signal
1517

16-
from FunctionCall x
18+
from FunctionCall signal
1719
where
18-
not isExcluded(x, SignalHandlersPackage::doNotCallSignalFromInterruptibleSignalHandlersQuery()) and
19-
x = any(SignalHandler handler).getReassertingCall()
20-
select x,
20+
not isExcluded(signal,
21+
SignalHandlersPackage::doNotCallSignalFromInterruptibleSignalHandlersQuery()) and
22+
signal = any(SignalHandler handler).getReassertingCall()
23+
select signal,
2124
"Reasserting handler bindings introduces a race condition on nonpersistent platforms and is redundant otherwise."

c/cert/src/rules/SIG35-C/DoNotReturnFromAComputationalExceptionHandler.ql

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,38 @@
66
* @precision very-high
77
* @problem.severity error
88
* @tags external/cert/id/sig35-c
9+
* correctness
10+
* security
911
* external/cert/obligation/rule
1012
*/
1113

1214
import cpp
1315
import codingstandards.c.cert
16+
import codingstandards.c.Signal
17+
import semmle.code.cpp.dataflow.DataFlow
1418

15-
from
19+
/**
20+
* CFG nodes preceeding a `ReturnStmt`
21+
*/
22+
ControlFlowNode reachesReturn(ReturnStmt return) {
23+
result = return
24+
or
25+
exists(ControlFlowNode mid |
26+
result = mid.getAPredecessor() and
27+
mid = reachesReturn(return) and
28+
// stop recursion on calls to `abort`, `_Exit` and "quick_exit"
29+
not result instanceof AbortCall
30+
)
31+
}
32+
33+
from ReturnStmt return, ComputationalExceptionSignal e
1634
where
17-
not isExcluded(x, SignalHandlersPackage::doNotReturnFromAComputationalExceptionHandlerQuery()) and
18-
select
35+
not isExcluded(return, SignalHandlersPackage::doNotReturnFromAComputationalExceptionHandlerQuery()) and
36+
exists(SignalHandler handler |
37+
handler = return.getEnclosingFunction() and
38+
// computational exception handler
39+
DataFlow::localExprFlow(e.getExpr(), handler.getRegistration().getArgument(0)) and
40+
// control flow reaches a return statement
41+
reachesReturn(return) = handler.getBlock()
42+
)
43+
select return, "Do not return from a $@ signal handler.", e, "computational exception"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
No expected results have yet been specified
1+
| test.c:10:1:10:1 | return ... | Do not return from a $@ signal handler. | test.c:13:10:13:15 | SIGFPE | computational exception |

c/cert/test/rules/SIG35-C/test.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <errno.h>
2+
#include <limits.h>
3+
#include <signal.h>
4+
#include <stdlib.h>
5+
6+
volatile sig_atomic_t eflag;
7+
8+
void sighandle(int s) { // NON_COMPLIANT
9+
eflag = 1;
10+
}
11+
12+
int f1(int argc, char *argv[]) {
13+
signal(SIGFPE, sighandle);
14+
15+
return 0;
16+
}
17+
18+
void sighandle2(int s) { // COMPLIANT
19+
eflag = 1;
20+
abort();
21+
}
22+
23+
int f2(int argc, char *argv[]) {
24+
signal(SIGFPE, sighandle2);
25+
return 0;
26+
}

c/common/src/codingstandards/c/Signal.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import cpp
22
import semmle.code.cpp.dataflow.DataFlow
33

4+
/**
5+
* A signal corresponding to a computational exception
6+
*/
7+
class ComputationalExceptionSignal extends MacroInvocation {
8+
ComputationalExceptionSignal() { this.getMacroName() = ["SIGFPE", "SIGILL", "SIGSEGV", "SIGBUS"] }
9+
}
10+
411
/**
512
* A call to function `signal`
613
*/
@@ -39,3 +46,16 @@ class SignalHandler extends Function {
3946
class AbortCall extends FunctionCall {
4047
AbortCall() { this.getTarget().hasGlobalName(["abort", "_Exit", "quick_exit"]) }
4148
}
49+
50+
/**
51+
* Models the type `sig_atomic_type`
52+
*/
53+
class SigAtomicType extends Type {
54+
SigAtomicType() {
55+
this.getName() = "sig_atomic_t"
56+
or
57+
this.(TypedefType).getBaseType() instanceof SigAtomicType
58+
or
59+
this.(SpecifiedType).getBaseType() instanceof SigAtomicType
60+
}
61+
}

rule_packages/c/SignalHandlers.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@
5555
"precision": "very-high",
5656
"severity": "error",
5757
"short_name": "DoNotCallSignalFromInterruptibleSignalHandlers",
58-
"tags": []
58+
"tags": [
59+
"correctness",
60+
"security"
61+
]
5962
}
6063
],
6164
"title": "Do not call signal() from within interruptible signal handlers"
@@ -72,7 +75,10 @@
7275
"precision": "very-high",
7376
"severity": "error",
7477
"short_name": "DoNotReturnFromAComputationalExceptionHandler",
75-
"tags": []
78+
"tags": [
79+
"correctness",
80+
"security"
81+
]
7682
}
7783
],
7884
"title": "Do not return from a computational exception signal handler"

0 commit comments

Comments
 (0)