From 020f7d7195aa368412898a84086495d7efad9841 Mon Sep 17 00:00:00 2001 From: Robert Muir Date: Wed, 6 May 2015 00:16:03 -0400 Subject: [PATCH] Load fielddata on behalf of scripts. If we have to do the one-time loading of fieldata, it requires more permissions than groovy scripts currently have (zero). This is because of RamUsageEstimator reflection and so on in PagedBytes. GroovySecurityTests only test a numeric field, so add a string field to the test (so pagedbytes fielddata gets created etc). --- .../elasticsearch/search/lookup/LeafDocLookup.java | 14 ++++++++++++-- .../elasticsearch/script/GroovySecurityTests.java | 6 +++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java b/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java index 7ae314e475653..ce330e80d9e3c 100644 --- a/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java +++ b/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.lookup; import com.google.common.collect.Maps; + import org.elasticsearch.common.Nullable; import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.fielddata.ScriptDocValues; @@ -26,6 +27,8 @@ import org.elasticsearch.index.mapper.MapperService; import org.apache.lucene.index.LeafReaderContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collection; import java.util.Map; @@ -73,11 +76,18 @@ public Object get(Object key) { String fieldName = key.toString(); ScriptDocValues scriptValues = localCacheFieldData.get(fieldName); if (scriptValues == null) { - FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName, types); + final FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName, types); if (mapper == null) { throw new IllegalArgumentException("No field found for [" + fieldName + "] in mapping with types " + Arrays.toString(types) + ""); } - scriptValues = fieldDataService.getForField(mapper).load(reader).getScriptValues(); + // load fielddata on behalf of the script: otherwise it would need additional permissions + // to deal with pagedbytes/ramusagestimator/etc + scriptValues = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ScriptDocValues run() { + return fieldDataService.getForField(mapper).load(reader).getScriptValues(); + } + }); localCacheFieldData.put(fieldName, scriptValues); } scriptValues.setNextDocId(docId); diff --git a/src/test/java/org/elasticsearch/script/GroovySecurityTests.java b/src/test/java/org/elasticsearch/script/GroovySecurityTests.java index c89d6187ddb5e..3051555ea287a 100644 --- a/src/test/java/org/elasticsearch/script/GroovySecurityTests.java +++ b/src/test/java/org/elasticsearch/script/GroovySecurityTests.java @@ -54,10 +54,14 @@ public void testEvilGroovyScripts() throws Exception { internalCluster().startNodesAsync(nodes, nodeSettings).get(); client().admin().cluster().prepareHealth().setWaitForNodes(nodes + "").get(); - client().prepareIndex("test", "doc", "1").setSource("foo", 5).setRefresh(true).get(); + client().prepareIndex("test", "doc", "1").setSource("foo", 5, "bar", "baz").setRefresh(true).get(); // Plain test assertSuccess(""); + // numeric field access + assertSuccess("def foo = doc['foo'].value; if (foo == null) { return 5; }"); + // string field access + assertSuccess("def bar = doc['bar'].value; if (foo == null) { return 5; }"); // List assertSuccess("def list = [doc['foo'].value, 3, 4]; def v = list.get(1); list.add(10)"); // Ranges