Skip to content

Commit 6b54cf7

Browse files
committed
[Java] refine AllowListChecker (#893)
* refine AllowListChecker * refine security warn log
1 parent 712d600 commit 6b54cf7

File tree

2 files changed

+96
-43
lines changed

2 files changed

+96
-43
lines changed

java/fury-core/src/main/java/io/fury/Fury.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1461,9 +1461,9 @@ private void finish() {
14611461
if (!requireClassRegistration) {
14621462
LOG.warn(
14631463
"Class registration isn't forced, unknown classes can be deserialized. "
1464-
+ "If the environment isn't 100% secure, please enable class registration by "
1464+
+ "If the environment isn't secure, please enable class registration by "
14651465
+ "`FuryBuilder#requireClassRegistration(true)` or configure ClassChecker by "
1466-
+ "`ClassResolver.setClassChecker`");
1466+
+ "`ClassResolver#setClassChecker`");
14671467
}
14681468
}
14691469

java/fury-core/src/main/java/io/fury/resolver/AllowListChecker.java

+94-41
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.fury.memory.MemoryBuffer;
2222
import io.fury.serializer.Serializer;
2323
import io.fury.util.LoggerFactory;
24+
import java.util.Collection;
2425
import java.util.HashSet;
2526
import java.util.Set;
2627
import java.util.WeakHashMap;
@@ -49,7 +50,7 @@ public enum CheckLevel {
4950
STRICT
5051
}
5152

52-
private final CheckLevel checkLevel;
53+
private volatile CheckLevel checkLevel;
5354
private final Set<String> allowList;
5455
private final Set<String> allowListPrefix;
5556
private final Set<String> disallowList;
@@ -71,8 +72,25 @@ public AllowListChecker(CheckLevel checkLevel) {
7172
listeners = new WeakHashMap<>();
7273
}
7374

75+
public CheckLevel getCheckLevel() {
76+
return checkLevel;
77+
}
78+
79+
public void setCheckLevel(CheckLevel checkLevel) {
80+
this.checkLevel = checkLevel;
81+
}
82+
7483
@Override
7584
public boolean checkClass(ClassResolver classResolver, String className) {
85+
try {
86+
lock.readLock().lock();
87+
return check(className);
88+
} finally {
89+
lock.readLock().unlock();
90+
}
91+
}
92+
93+
private boolean check(String className) {
7694
switch (checkLevel) {
7795
case DISABLE:
7896
return true;
@@ -106,41 +124,56 @@ public boolean checkClass(ClassResolver classResolver, String className) {
106124
}
107125
}
108126

109-
boolean containsPrefix(Set<String> set, Set<String> prefixSet, String className) {
110-
try {
111-
lock.readLock().lock();
112-
if (set.contains(className)) {
127+
static boolean containsPrefix(Set<String> set, Set<String> prefixSet, String className) {
128+
if (set.contains(className)) {
129+
return true;
130+
}
131+
for (String prefix : prefixSet) {
132+
if (className.startsWith(prefix)) {
113133
return true;
114134
}
115-
for (String prefix : prefixSet) {
116-
if (className.startsWith(prefix)) {
117-
return true;
118-
}
119-
}
120-
return false;
121-
} finally {
122-
lock.readLock().unlock();
123135
}
136+
return false;
124137
}
125138

126139
/**
127140
* Add class to allow list.
128141
*
129-
* @param classNameOrPrefix class name or class name prefix ends with *.
142+
* @param classNameOrPrefix class name or name prefix ends with *.
130143
*/
131144
public void allowClass(String classNameOrPrefix) {
132145
try {
133146
lock.writeLock().lock();
134-
if (classNameOrPrefix.endsWith("*")) {
135-
allowListPrefix.add(classNameOrPrefix.substring(0, classNameOrPrefix.length() - 1));
136-
} else {
137-
allowList.add(classNameOrPrefix);
147+
allow(classNameOrPrefix);
148+
} finally {
149+
lock.writeLock().unlock();
150+
}
151+
}
152+
153+
/**
154+
* Add classes to allow list.
155+
*
156+
* @param classNamesOrPrefixes class names or name prefixes ends with *.
157+
*/
158+
public void allowClasses(Collection<String> classNamesOrPrefixes) {
159+
try {
160+
lock.writeLock().lock();
161+
for (String namesOrPrefix : classNamesOrPrefixes) {
162+
allow(namesOrPrefix);
138163
}
139164
} finally {
140165
lock.writeLock().unlock();
141166
}
142167
}
143168

169+
private void allow(String classNameOrPrefix) {
170+
if (classNameOrPrefix.endsWith("*")) {
171+
allowListPrefix.add(classNameOrPrefix.substring(0, classNameOrPrefix.length() - 1));
172+
} else {
173+
allowList.add(classNameOrPrefix);
174+
}
175+
}
176+
144177
/**
145178
* Add class to disallow list.
146179
*
@@ -149,35 +182,55 @@ public void allowClass(String classNameOrPrefix) {
149182
public void disallowClass(String classNameOrPrefix) {
150183
try {
151184
lock.writeLock().lock();
152-
if (classNameOrPrefix.endsWith("*")) {
153-
String prefix = classNameOrPrefix.substring(0, classNameOrPrefix.length() - 1);
154-
disallowListPrefix.add(prefix);
155-
for (ClassResolver classResolver : listeners.keySet()) {
156-
try {
157-
classResolver.getFury().getJITContext().lock();
158-
// clear serializer may throw NullPointerException for field serialization.
159-
classResolver.setSerializers(prefix, DisallowSerializer.class);
160-
} finally {
161-
classResolver.getFury().getJITContext().unlock();
162-
}
163-
}
164-
} else {
165-
disallowList.add(classNameOrPrefix);
166-
for (ClassResolver classResolver : listeners.keySet()) {
167-
try {
168-
classResolver.getFury().getJITContext().lock();
169-
// clear serializer may throw NullPointerException for field serialization.
170-
classResolver.setSerializer(classNameOrPrefix, DisallowSerializer.class);
171-
} finally {
172-
classResolver.getFury().getJITContext().unlock();
173-
}
174-
}
185+
disallow(classNameOrPrefix);
186+
} finally {
187+
lock.writeLock().unlock();
188+
}
189+
}
190+
191+
/**
192+
* Add classes to disallow list.
193+
*
194+
* @param classNamesOrPrefixes class names or name prefixes ends with *.
195+
*/
196+
public void disallowClasses(Collection<String> classNamesOrPrefixes) {
197+
try {
198+
lock.writeLock().lock();
199+
for (String prefix : classNamesOrPrefixes) {
200+
disallow(prefix);
175201
}
176202
} finally {
177203
lock.writeLock().unlock();
178204
}
179205
}
180206

207+
private void disallow(String classNameOrPrefix) {
208+
if (classNameOrPrefix.endsWith("*")) {
209+
String prefix = classNameOrPrefix.substring(0, classNameOrPrefix.length() - 1);
210+
disallowListPrefix.add(prefix);
211+
for (ClassResolver classResolver : listeners.keySet()) {
212+
try {
213+
classResolver.getFury().getJITContext().lock();
214+
// clear serializer may throw NullPointerException for field serialization.
215+
classResolver.setSerializers(prefix, DisallowSerializer.class);
216+
} finally {
217+
classResolver.getFury().getJITContext().unlock();
218+
}
219+
}
220+
} else {
221+
disallowList.add(classNameOrPrefix);
222+
for (ClassResolver classResolver : listeners.keySet()) {
223+
try {
224+
classResolver.getFury().getJITContext().lock();
225+
// clear serializer may throw NullPointerException for field serialization.
226+
classResolver.setSerializer(classNameOrPrefix, DisallowSerializer.class);
227+
} finally {
228+
classResolver.getFury().getJITContext().unlock();
229+
}
230+
}
231+
}
232+
}
233+
181234
/**
182235
* Add listener to in response to disallow list. So if object of a class is serialized before,
183236
* future serialization will be refused.

0 commit comments

Comments
 (0)