46
46
* <ul>
47
47
* <li>{@code modifyThread} and {@code modifyThreadGroup} are required for any thread access
48
48
* checks: with these permissions, access is granted as long as the thread group is
49
- * the same or an ancestor ({@code sourceGroup.parentOf(targetGroup) == true}).
49
+ * the same or an ancestor ({@code sourceGroup.parentOf(targetGroup) == true}).
50
50
* <li>code without these permissions can do very little, except to interrupt itself. It may
51
51
* not even create new threads.
52
- * <li>very special cases (like test runners) that have {@link ThreadPermission} can violate
52
+ * <li>very special cases (like test runners) that have {@link ThreadPermission} can violate
53
53
* threadgroup security rules.
54
54
* </ul>
55
55
* <p>
56
56
* If java security debugging ({@code java.security.debug}) is enabled, and this SecurityManager
57
57
* is installed, it will emit additional debugging information when threadgroup access checks fail.
58
- *
58
+ *
59
59
* @see SecurityManager#checkAccess(Thread)
60
60
* @see SecurityManager#checkAccess(ThreadGroup)
61
61
* @see <a href="http://cs.oswego.edu/pipermail/concurrency-interest/2009-August/006508.html">
@@ -105,8 +105,10 @@ public static SecureSM createTestSecureSM() {
105
105
"com\\ .carrotsearch\\ .ant\\ .tasks\\ .junit4\\ .slave\\ ..*" ,
106
106
// eclipse test runner
107
107
"org\\ .eclipse.jdt\\ .internal\\ .junit\\ .runner\\ ..*" ,
108
- // intellij test runner
109
- "com\\ .intellij\\ .rt\\ .execution\\ .junit\\ ..*"
108
+ // intellij test runner (before IDEA version 2019.3)
109
+ "com\\ .intellij\\ .rt\\ .execution\\ .junit\\ ..*" ,
110
+ // intellij test runner (since IDEA version 2019.3)
111
+ "com\\ .intellij\\ .rt\\ .junit\\ ..*"
110
112
};
111
113
112
114
// java.security.debug support
@@ -122,7 +124,7 @@ public Boolean run() {
122
124
}
123
125
}
124
126
});
125
-
127
+
126
128
@ Override
127
129
@ SuppressForbidden (reason = "java.security.debug messages go to standard error" )
128
130
public void checkAccess (Thread t ) {
@@ -137,7 +139,7 @@ public void checkAccess(Thread t) {
137
139
throw e ;
138
140
}
139
141
}
140
-
142
+
141
143
@ Override
142
144
@ SuppressForbidden (reason = "java.security.debug messages go to standard error" )
143
145
public void checkAccess (ThreadGroup g ) {
@@ -157,7 +159,7 @@ private void debugThreadGroups(final ThreadGroup caller, final ThreadGroup targe
157
159
System .err .println ("access: caller group=" + caller );
158
160
System .err .println ("access: target group=" + target );
159
161
}
160
-
162
+
161
163
// thread permission logic
162
164
163
165
private static final Permission MODIFY_THREAD_PERMISSION = new RuntimePermission ("modifyThread" );
@@ -168,31 +170,31 @@ protected void checkThreadAccess(Thread t) {
168
170
169
171
// first, check if we can modify threads at all.
170
172
checkPermission (MODIFY_THREAD_PERMISSION );
171
-
173
+
172
174
// check the threadgroup, if its our thread group or an ancestor, its fine.
173
175
final ThreadGroup source = Thread .currentThread ().getThreadGroup ();
174
176
final ThreadGroup target = t .getThreadGroup ();
175
-
177
+
176
178
if (target == null ) {
177
179
return ; // its a dead thread, do nothing.
178
180
} else if (source .parentOf (target ) == false ) {
179
181
checkPermission (MODIFY_ARBITRARY_THREAD_PERMISSION );
180
182
}
181
183
}
182
-
184
+
183
185
private static final Permission MODIFY_THREADGROUP_PERMISSION = new RuntimePermission ("modifyThreadGroup" );
184
186
private static final Permission MODIFY_ARBITRARY_THREADGROUP_PERMISSION = new ThreadPermission ("modifyArbitraryThreadGroup" );
185
-
187
+
186
188
protected void checkThreadGroupAccess (ThreadGroup g ) {
187
189
Objects .requireNonNull (g );
188
190
189
191
// first, check if we can modify thread groups at all.
190
192
checkPermission (MODIFY_THREADGROUP_PERMISSION );
191
-
193
+
192
194
// check the threadgroup, if its our thread group or an ancestor, its fine.
193
195
final ThreadGroup source = Thread .currentThread ().getThreadGroup ();
194
196
final ThreadGroup target = g ;
195
-
197
+
196
198
if (source == null ) {
197
199
return ; // we are a dead thread, do nothing
198
200
} else if (source .parentOf (target ) == false ) {
@@ -205,7 +207,7 @@ protected void checkThreadGroupAccess(ThreadGroup g) {
205
207
public void checkExit (int status ) {
206
208
innerCheckExit (status );
207
209
}
208
-
210
+
209
211
/**
210
212
* The "Uwe Schindler" algorithm.
211
213
*
@@ -227,7 +229,7 @@ public Void run() {
227
229
exitMethodHit = className + '#' + methodName + '(' + status + ')' ;
228
230
continue ;
229
231
}
230
-
232
+
231
233
if (exitMethodHit != null ) {
232
234
if (classesThatCanExit == null ) {
233
235
break ;
@@ -240,15 +242,15 @@ public Void run() {
240
242
break ;
241
243
}
242
244
}
243
-
245
+
244
246
if (exitMethodHit == null ) {
245
247
// should never happen, only if JVM hides stack trace - replace by generic:
246
248
exitMethodHit = "JVM exit method" ;
247
249
}
248
250
throw new SecurityException (exitMethodHit + " calls are not allowed" );
249
251
}
250
252
});
251
-
253
+
252
254
// we passed the stack check, delegate to super, so default policy can still deny permission:
253
255
super .checkExit (status );
254
256
}
0 commit comments