mirror of https://github.com/apache/lucene.git
Merge remote-tracking branch 'origin/master' into gradle-master
This commit is contained in:
commit
206d62b9d5
|
@ -19,6 +19,12 @@ package org.apache.solr.handler.dataimport;
|
|||
import static org.apache.solr.handler.dataimport.DataImportHandlerException.wrapAndThrow;
|
||||
import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.script.Invocable;
|
||||
|
@ -46,7 +52,16 @@ public class ScriptTransformer extends Transformer {
|
|||
private String functionName;
|
||||
|
||||
@Override
|
||||
public Object transformRow(Map<String, Object> row, Context context) {
|
||||
public Object transformRow(Map<String,Object> row, Context context) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
return transformRowUnsafe(row, context);
|
||||
}
|
||||
}, SCRIPT_SANDBOX);
|
||||
}
|
||||
|
||||
public Object transformRowUnsafe(Map<String, Object> row, Context context) {
|
||||
try {
|
||||
if (engine == null)
|
||||
initEngine(context);
|
||||
|
@ -84,7 +99,17 @@ public class ScriptTransformer extends Transformer {
|
|||
+ scriptEngine.getClass().getName());
|
||||
}
|
||||
try {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws ScriptException {
|
||||
scriptEngine.eval(scriptText);
|
||||
return null;
|
||||
}
|
||||
}, SCRIPT_SANDBOX);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (ScriptException) e.getException();
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
wrapAndThrow(SEVERE, e, "'eval' failed with language: " + scriptLang
|
||||
+ " and script: \n" + scriptText);
|
||||
|
@ -99,4 +124,8 @@ public class ScriptTransformer extends Transformer {
|
|||
return functionName;
|
||||
}
|
||||
|
||||
// sandbox for script code: zero permissions
|
||||
private static final AccessControlContext SCRIPT_SANDBOX =
|
||||
new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, null) });
|
||||
|
||||
}
|
||||
|
|
|
@ -56,6 +56,28 @@ public class TestScriptTransformer extends AbstractDataImportHandlerTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvil() {
|
||||
assumeTrue("This test only works with security manager", System.getSecurityManager() != null);
|
||||
String script = "function f1(row) {"
|
||||
+ "var os = Packages.java.lang.System.getProperty('os.name');"
|
||||
+ "row.put('name', os);"
|
||||
+ "return row;\n"
|
||||
+ "}";
|
||||
|
||||
Context context = getContext("f1", script);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", "Scott");
|
||||
EntityProcessorWrapper sep = new EntityProcessorWrapper(new SqlEntityProcessor(), null, null);
|
||||
sep.init(context);
|
||||
DataImportHandlerException expected = expectThrows(DataImportHandlerException.class, () -> {
|
||||
sep.applyTransformer(map);
|
||||
});
|
||||
assumeFalse("This JVM does not have JavaScript installed. Test Skipped.",
|
||||
expected.getMessage().startsWith("Cannot load Script Engine for language"));
|
||||
assertTrue(expected.getCause().toString(), SecurityException.class.isAssignableFrom(expected.getCause().getClass()));
|
||||
}
|
||||
|
||||
private Context getContext(String funcName, String script) {
|
||||
List<Map<String, String>> fields = new ArrayList<>();
|
||||
Map<String, String> entity = new HashMap<>();
|
||||
|
|
|
@ -41,6 +41,12 @@ import java.io.InputStream;
|
|||
import java.io.Reader;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Set;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.ArrayList;
|
||||
|
@ -269,7 +275,7 @@ public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcesso
|
|||
}
|
||||
|
||||
for (ScriptFile scriptFile : scriptFiles) {
|
||||
ScriptEngine engine = null;
|
||||
final ScriptEngine engine;
|
||||
if (null != engineName) {
|
||||
engine = scriptEngineManager.getEngineByName(engineName);
|
||||
if (engine == null) {
|
||||
|
@ -314,7 +320,17 @@ public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcesso
|
|||
Reader scriptSrc = scriptFile.openReader(resourceLoader);
|
||||
|
||||
try {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws ScriptException {
|
||||
engine.eval(scriptSrc);
|
||||
return null;
|
||||
}
|
||||
}, SCRIPT_SANDBOX);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (ScriptException) e.getException();
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||
"Unable to evaluate script: " +
|
||||
|
@ -424,6 +440,15 @@ public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcesso
|
|||
* cast to a java Boolean.
|
||||
*/
|
||||
private boolean invokeFunction(String name, Object... cmd) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return invokeFunctionUnsafe(name, cmd);
|
||||
}
|
||||
}, SCRIPT_SANDBOX);
|
||||
}
|
||||
|
||||
private boolean invokeFunctionUnsafe(String name, Object... cmd) {
|
||||
|
||||
for (EngineInfo engine : engines) {
|
||||
try {
|
||||
|
@ -496,4 +521,8 @@ public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcesso
|
|||
(input, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
// sandbox for script code: zero permissions
|
||||
private static final AccessControlContext SCRIPT_SANDBOX =
|
||||
new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, null) });
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
var sys = Packages.java.lang.System;
|
||||
|
||||
function processAdd(cmd) {
|
||||
sys.getProperty("os.name");
|
||||
}
|
||||
|
||||
function processDelete(cmd) {
|
||||
}
|
||||
|
||||
function processMergeIndexes(cmd) {
|
||||
}
|
||||
|
||||
function processCommit(cmd) {
|
||||
}
|
||||
|
||||
function processRollback(cmd) {
|
||||
}
|
||||
|
||||
function finish() {
|
||||
}
|
||||
|
|
@ -117,4 +117,10 @@
|
|||
</processor>
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<updateRequestProcessorChain name="evil">
|
||||
<processor class="solr.StatelessScriptUpdateProcessorFactory">
|
||||
<str name="script">evil.js</str>
|
||||
</processor>
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
</config>
|
||||
|
|
|
@ -259,4 +259,14 @@ public class StatelessScriptUpdateProcessorFactoryTest extends UpdateProcessorTe
|
|||
|
||||
}
|
||||
|
||||
public void testScriptSandbox() throws Exception {
|
||||
assumeTrue("This test only works with security manager", System.getSecurityManager() != null);
|
||||
expectThrows(SecurityException.class, () -> {
|
||||
processAdd("evil",
|
||||
doc(f("id", "5"),
|
||||
f("name", " foo "),
|
||||
f("subject", "BAR")));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue