Repository navigation
Expand file tree
/
Copy pathFileWritable.qll
More file actions
142 lines (135 loc) · 5 KB
/
Copy pathFileWritable.qll
File metadata and controls
142 lines (135 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
overlay[local?]
module;
import java
/**
* A `File.setWritable(..)` method.
*/
class SetWritable extends Method {
SetWritable() {
this.getDeclaringType() instanceof TypeFile and
this.hasName("setWritable")
}
}
/**
* Gets an `EnumConstant` that may be in the `Set` of `Enum`s represented by `enumSetRef`.
*/
private EnumConstant getAContainedEnumConstant(Expr enumSetRef) {
enumSetRef
.getType()
.(RefType)
.getAnAncestor()
.getSourceDeclaration()
.hasQualifiedName("java.util", "Set") and
(
// The set is defined inline using `EnumSet.of(...)`.
exists(MethodCall enumSetOf |
enumSetOf = enumSetRef and
enumSetOf.getMethod().hasName("of") and
enumSetOf
.getMethod()
.getDeclaringType()
.getSourceDeclaration()
.hasQualifiedName("java.util", "EnumSet")
|
// Any argument to `EnumSet.of(...)` is an `EnumConstant`.
result = enumSetOf.getAnArgument().(VarAccess).getVariable()
)
or
// The set reference is an access of a variable...
exists(VarAccess enumSetAccess | enumSetAccess = enumSetRef |
// ...if the definition contains a value...
result = getAContainedEnumConstant(enumSetAccess.getVariable().getAnAssignedValue())
or
// ...or the value is added to the set.
exists(MethodCall addToSet |
addToSet.getQualifier() = enumSetAccess.getVariable().getAnAccess()
|
// Call to `add(..)` on the enum set variable.
addToSet.getMethod().hasName("add") and
result = addToSet.getArgument(0).(VarAccess).getVariable()
or
// Call to `addAll(..)` on the enum set variable.
addToSet.getMethod().hasName("addAll") and
result = getAContainedEnumConstant(addToSet.getArgument(0))
)
)
)
}
/**
* Gets a `VarAccess` to a `File` that is converted to a `Path` by `pathExpr`.
*/
private VarAccess getFileForPathConversion(Expr pathExpr) {
pathExpr.getType().(RefType).hasQualifiedName("java.nio.file", "Path") and
(
// Look for conversion from `File` to `Path` using `file.toPath()`.
exists(MethodCall fileToPath |
fileToPath = pathExpr and
result = fileToPath.getQualifier() and
fileToPath.getMethod().hasName("toPath") and
fileToPath.getMethod().getDeclaringType() instanceof TypeFile
)
or
// Look for the pattern `Paths.get(file.get*Path())` for converting between a `File` and a `Path`.
exists(MethodCall pathsGet, MethodCall fileGetPath |
pathsGet = pathExpr and
pathsGet.getMethod().hasName("get") and
pathsGet.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Paths") and
fileGetPath = pathsGet.getArgument(0) and
result = fileGetPath.getQualifier()
|
fileGetPath.getMethod().hasName("getPath") or
fileGetPath.getMethod().hasName("getAbsolutePath") or
fileGetPath.getMethod().hasName("getCanonicalPath")
)
)
}
/**
* Holds if `fileAccess` is used in the `setWorldWritable` to set the file to be world writable.
*/
private predicate fileSetWorldWritable(VarAccess fileAccess, Expr setWorldWritable) {
// Calls to `File.setWritable(.., false)`.
exists(MethodCall fileSetWritable |
// A call to the `setWritable` method.
fileSetWritable.getMethod() instanceof SetWritable and
// Where we may be setting `writable` to `true`.
not fileSetWritable.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false and
// The permission applies to everyone.
fileSetWritable.getArgument(1).(CompileTimeConstantExpr).getBooleanValue() = false and
setWorldWritable = fileSetWritable and
fileAccess = fileSetWritable.getQualifier()
)
or
// Calls to `Files.setPosixFilePermissions(...)`.
exists(MethodCall setPosixPerms |
setPosixPerms = setWorldWritable and
setPosixPerms.getMethod().hasName("setPosixFilePermissions") and
setPosixPerms.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Files") and
(
fileAccess = setPosixPerms.getArgument(0)
or
// The argument was a file that has been converted to a path.
fileAccess = getFileForPathConversion(setPosixPerms.getArgument(0))
)
|
// The second argument is a set of `FilePermission`s.
getAContainedEnumConstant(setPosixPerms.getArgument(1)).hasName("OTHERS_WRITE")
)
or
// Calls to something that indirectly sets the file permissions.
exists(Call call, int parameterPos, VarAccess nestedFileAccess |
call = setWorldWritable and
fileSetWorldWritable(nestedFileAccess, _) and
call.getCallee().getParameter(parameterPos) = nestedFileAccess.getVariable() and
fileAccess = call.getArgument(parameterPos)
)
}
/**
* An expression that, directly or indirectly, makes the file argument world writable.
*/
class SetFileWorldWritable extends Expr {
SetFileWorldWritable() { fileSetWorldWritable(_, this) }
/**
* Gets the `VarAccess` representing the file that is set world writable.
*/
VarAccess getFileVarAccess() { fileSetWorldWritable(result, this) }
}