Skip to content

Commit 3dccc29

Browse files
committed
blocked signals fixed
1 parent 4e7e937 commit 3dccc29

File tree

2 files changed

+36
-34
lines changed

2 files changed

+36
-34
lines changed

cpp/src/security/AsyncUnsafeSignalHandler/AsyncUnsafeSignalHandler.ql

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ predicate isSignal(FunctionCall signalCall, Function signalHandler) {
5757
* struct sigaction sigactVar = ...
5858
* sigaction(SIGX, &sigactVar, ...)
5959
*/
60-
predicate isSigaction(FunctionCall sigactionCall, Function signalHandler, boolean isReentrancyBlocked) {
61-
exists(Variable sigactVar, Struct sigactStruct, Field handlerField |
60+
predicate isSigaction(FunctionCall sigactionCall, Function signalHandler, Variable sigactVar) {
61+
exists(Struct sigactStruct, Field handlerField |
6262
sigactionCall.getTarget().getName() = "sigaction"
6363
and sigactionCall.getArgument(1).getAChild*() = sigactVar.getAnAccess()
6464

@@ -79,45 +79,46 @@ predicate isSigaction(FunctionCall sigactionCall, Function signalHandler, boolea
7979
and dfa.getQualifier+() = sigactVar.getAnAccess()
8080
)
8181
or
82-
exists(VariableDeclarationEntry varDec, ClassAggregateLiteral init |
82+
exists(ClassAggregateLiteral initLit |
8383
// struct sigaction sigactVar = {.sa_sigaction = signalHandler};
84-
varDec.getVariable() = sigactVar
85-
and sigactVar.getInitializer().getExpr() = init
86-
and signalHandler.getAnAccess() = init.getAFieldExpr(handlerField).getAChild*()
87-
88-
// new signals are blocked via sa_mask
89-
and if exists(Field mask | mask.getName() = "sa_mask" and exists(init.getAFieldExpr(mask))) then
90-
isReentrancyBlocked = true
91-
else
92-
isReentrancyBlocked = false
84+
// varDec.getVariable() = sigactVar
85+
sigactVar.getInitializer().getExpr() = initLit
86+
and signalHandler.getAnAccess() = initLit.getAFieldExpr(handlerField).getAChild*()
9387
)
9488
)
95-
96-
// new signals are blocked via sa_mask
97-
and if (isReentrancyBlocked = true or exists(ValueFieldAccess dfa |
98-
dfa.getQualifier+() = sigactVar.getAnAccess()
99-
and dfa.getTarget().getName() = "sa_mask"
100-
)) then
101-
isReentrancyBlocked = true
102-
else
103-
isReentrancyBlocked = false
10489
)
10590
}
10691

107-
string fmtMsg(boolean isReentrancyBlocked) {
108-
(isReentrancyBlocked = true and result = "")
92+
predicate isSignalDeliveryBlocked(Variable sigactVar) {
93+
// TODO: should only find writes and for specific signals
94+
exists(ValueFieldAccess dfa |
95+
dfa.getQualifier+() = sigactVar.getAnAccess() and dfa.getTarget().getName() = "sa_mask"
96+
)
10997
or
110-
(isReentrancyBlocked = false and result = "Delivery of new signals may be not blocked when the handler executes. ")
98+
exists(Field mask |
99+
mask.getName() = "sa_mask"
100+
and exists(sigactVar.getInitializer().getExpr().(ClassAggregateLiteral).getAFieldExpr(mask))
101+
)
102+
}
103+
104+
string deliveryNotBlockedMsg() {
105+
result = "Delivery of new signals may be not blocked when the handler executes. "
111106
}
112107

113-
from FunctionCall fc, Function signalHandler, boolean isReentrancyBlocked
108+
from FunctionCall fc, Function signalHandler, string msg
114109
where
115110
isAsyncUnsafe(signalHandler)
116111
and (
117-
(isSignal(fc, signalHandler) and isReentrancyBlocked = false)
112+
(isSignal(fc, signalHandler) and msg = deliveryNotBlockedMsg())
118113
or
119-
isSigaction(fc, signalHandler, isReentrancyBlocked)
114+
exists(Variable sigactVar |
115+
isSigaction(fc, signalHandler, sigactVar)
116+
and if isSignalDeliveryBlocked(sigactVar) then
117+
msg = ""
118+
else
119+
msg = deliveryNotBlockedMsg()
120+
)
120121
)
121-
select signalHandler, "is a non-trivial signal handler that uses not async-safe functions. " + fmtMsg(isReentrancyBlocked) +
122+
select signalHandler, "is a non-trivial signal handler that uses not async-safe functions. " + msg +
122123
"Handler is registered by $@", fc, fc.toString()
123124

cpp/test/query-tests/security/AsyncUnsafeSignalHandler/AsyncUnsafeSignalHandler.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ int main() {
9292
_Exit(EXIT_FAILURE);
9393
}
9494

95-
// Unsafe example
95+
// Unsafe example 1
9696
if (signal(SIGALRM, unsafe_handler) == SIG_ERR) {
9797
perror("Unable to catch SIGALRM");
9898
_Exit(EXIT_FAILURE);
9999
}
100100

101-
// Another unsafe example
101+
// Unsafe example 2
102102
// TODO: decide which signals are exploitable and should produce findings
103103
struct sigaction act = { 0 };
104104
act.sa_flags = SA_SIGINFO;
@@ -108,14 +108,14 @@ int main() {
108108
_Exit(EXIT_FAILURE);
109109
}
110110

111-
// Yet another unsafe
111+
// Unsafe example 3
112112
struct sigaction act2 = {.sa_flags = SA_SIGINFO, .sa_sigaction = unsafe_handler2};
113113
if (sigaction(SIGALRM, &act2, NULL) == -1) {
114114
perror("sigaction 2");
115115
_Exit(EXIT_FAILURE);
116116
}
117117

118-
// Let's call these safe, because some signals are blocked
118+
// Unsafe example 4
119119
// TODO: not every masked signals should indicate safe signal handling
120120
sigset_t sigset;
121121
sigemptyset(&sigset);
@@ -126,14 +126,15 @@ int main() {
126126
_Exit(EXIT_FAILURE);
127127
}
128128

129+
// Unsafe example 5
129130
struct sigaction act4 = {.sa_flags = SA_SIGINFO, .sa_sigaction = unsafe_handler2};
130131
act4.sa_mask = sigset;
131132
if (sigaction(SIGSEGV, &act4, NULL) == -1) {
132133
perror("sigaction 4");
133134
_Exit(EXIT_FAILURE);
134135
}
135136

136-
// TODO: this example should be not marked as finding
137+
// Unsafe example 6
137138
struct sigaction act5 = {.sa_mask = sigset};
138139
act5.sa_flags = SA_SIGINFO;
139140
act5.sa_sigaction = &unsafe_handler2;
@@ -142,7 +143,7 @@ int main() {
142143
_Exit(EXIT_FAILURE);
143144
}
144145

145-
// indirect handler registration
146+
// Unsafe example 7, indirect handler registration
146147
if(register_signal(SIGALRM, df_handler)) {
147148
_exit(EXIT_FAILURE);
148149
}

0 commit comments

Comments
 (0)