mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
C++: Add models for BSD-style send and recv functions.
This commit is contained in:
@@ -28,3 +28,5 @@ private import implementations.Swap
|
||||
private import implementations.GetDelim
|
||||
private import implementations.SmartPointer
|
||||
private import implementations.Sscanf
|
||||
private import implementations.Send
|
||||
private import implementations.Recv
|
||||
|
||||
73
cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll
Normal file
73
cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `recv` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/** The function `recv` and its assorted variants */
|
||||
private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunction {
|
||||
Recv() {
|
||||
this.hasGlobalName([
|
||||
"recv", // recv(socket, dest, len, flags)
|
||||
"recvfrom", // recvfrom(socket, dest, len, flags, from, fromlen)
|
||||
"read", // read(socket, dest, len)
|
||||
"pread" // pread(socket, dest, len, offset)
|
||||
])
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getParameter(index).getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
bufParam = 1 and countParam = 2
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { this.hasGlobalName("recvfrom") and bufParam = 4 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) {
|
||||
bufParam = 1
|
||||
or
|
||||
this.hasGlobalName("recvfrom") and bufParam = 4
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
this.hasGlobalName("recvfrom") and
|
||||
(
|
||||
i = 4 and buffer = true
|
||||
or
|
||||
i = 5 and buffer = false
|
||||
)
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 1 and buffer = true and mustWrite = false
|
||||
or
|
||||
this.hasGlobalName("recvfrom") and
|
||||
(
|
||||
i = 4 and buffer = true and mustWrite = false
|
||||
or
|
||||
i = 5 and buffer = false and mustWrite = false
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
|
||||
output.isParameterDeref(1) and
|
||||
description = "Buffer read by " + this.getName()
|
||||
}
|
||||
}
|
||||
55
cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll
Normal file
55
cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `send` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/** The function `send` and its assorted variants */
|
||||
private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunctionSink {
|
||||
Send() {
|
||||
this.hasGlobalName([
|
||||
"send", // send(socket, buf, len, flags)
|
||||
"sendto", // sendto(socket, buf, len, flags, to, tolen)
|
||||
"write" // write(socket, buf, len);
|
||||
])
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getParameter(index).getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
bufParam = 1 and countParam = 2
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 1 }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 1 and buffer = true
|
||||
or
|
||||
exists(this.getParameter(4)) and i = 4 and buffer = false
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
override predicate hasRemoteFlowSink(FunctionInput input, string description) {
|
||||
input.isParameterDeref(1) and description = "Buffer sent by " + this.getName()
|
||||
}
|
||||
}
|
||||
@@ -29,3 +29,12 @@ abstract class LocalFlowFunction extends Function {
|
||||
*/
|
||||
abstract predicate hasLocalFlowSource(FunctionOutput output, string description);
|
||||
}
|
||||
|
||||
/** A library function that sends data over a network connection. */
|
||||
abstract class RemoteFlowFunctionSink extends Function {
|
||||
/**
|
||||
* Holds if data described by `description` flows into `input` to a call to this function, and is then
|
||||
* send over a network connection.
|
||||
*/
|
||||
abstract predicate hasRemoteFlowSink(FunctionInput input, string description);
|
||||
}
|
||||
|
||||
@@ -98,3 +98,31 @@ private class ArgvSource extends LocalFlowSource {
|
||||
|
||||
override string getSourceType() { result = "a command-line argument" }
|
||||
}
|
||||
|
||||
/** A remote data flow sink. */
|
||||
abstract class RemoteFlowSink extends DataFlow::Node {
|
||||
/** Gets a string that describes the type of this flow sink. */
|
||||
abstract string getSinkType();
|
||||
}
|
||||
|
||||
private class RemoteParameterSink extends RemoteFlowSink {
|
||||
string sourceType;
|
||||
|
||||
RemoteParameterSink() {
|
||||
exists(RemoteFlowFunctionSink func, FunctionInput input, CallInstruction call, int index |
|
||||
func.hasRemoteFlowSink(input, sourceType) and call.getStaticCallTarget() = func
|
||||
|
|
||||
exists(ReadSideEffectInstruction read |
|
||||
call = read.getPrimaryInstruction() and
|
||||
read.getIndex() = index and
|
||||
this.asOperand() = read.getSideEffectOperand() and
|
||||
input.isParameterDerefOrQualifierObject(index)
|
||||
)
|
||||
or
|
||||
input.isParameterOrQualifierAddress(index) and
|
||||
this.asOperand() = call.getArgumentOperand(index)
|
||||
)
|
||||
}
|
||||
|
||||
override string getSinkType() { result = sourceType }
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.security.SecurityOptions
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
|
||||
/**
|
||||
* Extend this class to customize the security queries for
|
||||
@@ -60,7 +61,7 @@ class SecurityOptions extends string {
|
||||
functionCall.getTarget().hasGlobalName(fname) and
|
||||
exists(functionCall.getArgument(arg)) and
|
||||
(
|
||||
fname = ["read", "recv", "recvmsg"] and arg = 1
|
||||
fname = "recvmsg" and arg = 1
|
||||
or
|
||||
fname = "getaddrinfo" and arg = 3
|
||||
or
|
||||
@@ -68,6 +69,12 @@ class SecurityOptions extends string {
|
||||
(arg = 1 or arg = 4 or arg = 5)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(RemoteFlowFunction remote, FunctionOutput output |
|
||||
functionCall.getTarget() = remote and
|
||||
output.isParameterDerefOrQualifierObject(arg) and
|
||||
remote.hasRemoteFlowSource(output, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,6 +88,12 @@ class SecurityOptions extends string {
|
||||
userInputReturn(fname)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(RemoteFlowFunction remote, FunctionOutput output |
|
||||
functionCall.getTarget() = remote and
|
||||
(output.isReturnValue() or output.isReturnValueDeref()) and
|
||||
remote.hasRemoteFlowSource(output, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user